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]

More memory reductions for DOM


Similar to the previous DOM patch, this patch moves a block local
varray to a global varray.  This time it's avail_exprs.

Unlike stmts_to_rescan, avail_exprs doesn't have a convenient way to
map a particular entry in the varray to a block (which we need to
facilitate unwinding).  So instead we push a null marker on the
stack and unwind to the first null marker we see.

This reduces the number of varrays we create for unwinding the 
expression table from > 9000 to 987 with roughly a 500k reduction
in the amount of varray memory we allocate for Gerald's testcase.

I'll note that something added ~20M of GC allocated memory for
Gerald's testcase in the last 24-48 hours (though compilation time
seems to have noticably improved).  So any improvements I'm
making in terms of memory consumption are probably being dwarfed
by ongoing merging of queued development code.


Bootstrapped and regression tested on i686-pc-linux-gnu.

	* tree-ssa-dom.c (avail_exprs_stack): New global varray.
	(struct dom_walk_block_data): Remove avail_exprs member.
	(tree_ssa_dominator_optimize): Initialize avail_exprs_stack.
	(lookup_avail_expr): No longer need to pass in address of
	the block local available exprs stack.  All callers changed.
	(simplify_cond_and_lookup_avail_expr): Similarly.
	(simplify_switch_and_lookup_avail_expr): Similarly.
	(get_eq_expr_value, record_cond): Likewise.
	(record_dominating_conditions): Likewise.
	(update_rhs_and_lookup_avail_expr): Likewise.
	(record_equivalences_from_stmt): Likewise.
	(dom_opt_initialize_block_local_data): No longer test state of
	block local avail_exprs.
	(dom_opt_initialize_block): Mark unwind point in the global
	avail_expr stack.
	(remove_expressions_from_table): Update to unwind to the 
	most recent unwind marker in the global avail_expr stack.
	All callers changed.
	(dom_opt_finalize_block): Mark unwind point in the global
	avail_expr stack as needed.
	(record_cond): Push elements into the global avail_exprs stack.
	
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dom.c,v
retrieving revision 2.38
diff -c -p -r2.38 tree-ssa-dom.c
*** tree-ssa-dom.c	14 Sep 2004 15:15:34 -0000	2.38
--- tree-ssa-dom.c	15 Sep 2004 04:30:06 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 53,58 ****
--- 53,65 ----
     in this table.  */
  static htab_t avail_exprs;
  
+ /* Stack of available expressions in AVAIL_EXPRs.  Each block pushes
any
+    expressions it enters into the hash table along with a marker entry
+    (null).  When we finsh processing the block, we pop off entries and
+    remove the expressions from the global hash table until we hit the
+    marker.  */
+ static varray_type avail_exprs_stack;
+ 
  /* Stack of statements we need to rescan during finalization for newly
     exposed variables.
  
*************** static varray_type vrp_data;
*** 180,191 ****
  
  struct dom_walk_block_data
  {
-   /* Array of all the expressions entered into the global expression
-      hash table by this block.  During finalization we use this array
to
-      know what expressions to remove from the global expression hash
-      table.  */
-   varray_type avail_exprs;
- 
    /* Array of dest, src pairs that need to be restored during
finalization
       into the global const/copies table during finalization.  */
    varray_type const_and_copies;
--- 187,192 ----
*************** static void optimize_stmt (struct dom_wa
*** 217,239 ****
  			   block_stmt_iterator);
  static inline tree get_value_for (tree, varray_type table);
  static inline void set_value_for (tree, tree, varray_type table);
! static tree lookup_avail_expr (tree, varray_type *, bool);
! static struct eq_expr_value get_eq_expr_value (tree, int, varray_type
*,
  					       basic_block, varray_type *);
  static hashval_t avail_expr_hash (const void *);
  static hashval_t real_avail_expr_hash (const void *);
  static int avail_expr_eq (const void *, const void *);
  static void htab_statistics (FILE *, htab_t);
! static void record_cond (tree, tree, varray_type *);
! static void record_dominating_conditions (tree, varray_type *);
  static void record_const_or_copy (tree, tree, varray_type *);
  static void record_equality (tree, tree, varray_type *);
! static tree update_rhs_and_lookup_avail_expr (tree, tree, varray_type
*, bool);
  static tree simplify_rhs_and_lookup_avail_expr (struct dom_walk_data
*,
  						tree, int);
! static tree simplify_cond_and_lookup_avail_expr (tree, varray_type *,
! 						 stmt_ann_t, int);
! static tree simplify_switch_and_lookup_avail_expr (tree, varray_type
*, int);
  static tree find_equivalent_equality_comparison (tree);
  static void record_range (tree, basic_block, varray_type *);
  static bool extract_range_from_cond (tree, tree *, tree *, int *);
--- 218,239 ----
  			   block_stmt_iterator);
  static inline tree get_value_for (tree, varray_type table);
  static inline void set_value_for (tree, tree, varray_type table);
! static tree lookup_avail_expr (tree, bool);
! static struct eq_expr_value get_eq_expr_value (tree, int,
  					       basic_block, varray_type *);
  static hashval_t avail_expr_hash (const void *);
  static hashval_t real_avail_expr_hash (const void *);
  static int avail_expr_eq (const void *, const void *);
  static void htab_statistics (FILE *, htab_t);
! static void record_cond (tree, tree);
! static void record_dominating_conditions (tree);
  static void record_const_or_copy (tree, tree, varray_type *);
  static void record_equality (tree, tree, varray_type *);
! static tree update_rhs_and_lookup_avail_expr (tree, tree, bool);
  static tree simplify_rhs_and_lookup_avail_expr (struct dom_walk_data
*,
  						tree, int);
! static tree simplify_cond_and_lookup_avail_expr (tree, stmt_ann_t,
int);
! static tree simplify_switch_and_lookup_avail_expr (tree, int);
  static tree find_equivalent_equality_comparison (tree);
  static void record_range (tree, basic_block, varray_type *);
  static bool extract_range_from_cond (tree, tree *, tree *, int *);
*************** static void record_equivalences_from_inc
*** 242,248 ****
  						    basic_block);
  static bool eliminate_redundant_computations (struct dom_walk_data *,
  					      tree, stmt_ann_t);
! static void record_equivalences_from_stmt (tree, varray_type *,
varray_type *,
  					   int, stmt_ann_t);
  static void thread_across_edge (struct dom_walk_data *, edge);
  static void dom_opt_finalize_block (struct dom_walk_data *,
basic_block);
--- 242,248 ----
  						    basic_block);
  static bool eliminate_redundant_computations (struct dom_walk_data *,
  					      tree, stmt_ann_t);
! static void record_equivalences_from_stmt (tree, varray_type *,
  					   int, stmt_ann_t);
  static void thread_across_edge (struct dom_walk_data *, edge);
  static void dom_opt_finalize_block (struct dom_walk_data *,
basic_block);
*************** static void dom_opt_initialize_block_loc
*** 250,258 ****
  						 basic_block, bool);
  static void dom_opt_initialize_block (struct dom_walk_data *,
basic_block);
  static void cprop_into_phis (struct dom_walk_data *, basic_block);
! static void remove_local_expressions_from_table (varray_type locals,
! 						 unsigned limit,
! 						 htab_t table);
  static void restore_vars_to_original_value (varray_type locals,
  					    unsigned limit, 
  					    varray_type table);
--- 250,256 ----
  						 basic_block, bool);
  static void dom_opt_initialize_block (struct dom_walk_data *,
basic_block);
  static void cprop_into_phis (struct dom_walk_data *, basic_block);
! static void remove_local_expressions_from_table (void);
  static void restore_vars_to_original_value (varray_type locals,
  					    unsigned limit, 
  					    varray_type table);
*************** tree_ssa_dominator_optimize (void)
*** 314,319 ****
--- 312,318 ----
  
    /* Create our hash tables.  */
    avail_exprs = htab_create (1024, real_avail_expr_hash,
avail_expr_eq, free);
+   VARRAY_TREE_INIT (avail_exprs_stack, 20, "Available expression
stack");
    VARRAY_TREE_INIT (const_and_copies, num_ssa_names,
"const_and_copies");
    nonzero_vars = BITMAP_XMALLOC ();
    VARRAY_GENERIC_PTR_INIT (vrp_data, num_ssa_names, "vrp_data");
*************** thread_across_edge (struct dom_walk_data
*** 489,495 ****
        if (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME)
  	cached_lhs = TREE_OPERAND (stmt, 1);
        else
! 	cached_lhs = lookup_avail_expr (stmt, NULL, false);
  
        lhs = TREE_OPERAND (stmt, 0);
  
--- 488,494 ----
        if (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME)
  	cached_lhs = TREE_OPERAND (stmt, 1);
        else
! 	cached_lhs = lookup_avail_expr (stmt, false);
  
        lhs = TREE_OPERAND (stmt, 0);
  
*************** thread_across_edge (struct dom_walk_data
*** 535,541 ****
  	    }
  
  	  /* Try to lookup the new expression.  */
! 	  cached_lhs = lookup_avail_expr (stmt, NULL, false);
  
  	  /* Restore the statement's original uses/defs.  */
  	  for (i = 0; i < NUM_USES (uses); i++)
--- 534,540 ----
  	    }
  
  	  /* Try to lookup the new expression.  */
! 	  cached_lhs = lookup_avail_expr (stmt, false);
  
  	  /* Restore the statement's original uses/defs.  */
  	  for (i = 0; i < NUM_USES (uses); i++)
*************** thread_across_edge (struct dom_walk_data
*** 654,665 ****
  	     otherwise look it up in the hash tables.  */
  	  cached_lhs = local_fold (COND_EXPR_COND (dummy_cond));
  	  if (! is_gimple_min_invariant (cached_lhs))
! 	    cached_lhs = lookup_avail_expr (dummy_cond, NULL, false);
   	  if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs))
  	    {
  	      cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond,
  								NULL,
- 								NULL,
  								false);
  	    }
  	}
--- 653,663 ----
  	     otherwise look it up in the hash tables.  */
  	  cached_lhs = local_fold (COND_EXPR_COND (dummy_cond));
  	  if (! is_gimple_min_invariant (cached_lhs))
! 	    cached_lhs = lookup_avail_expr (dummy_cond, false);
   	  if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs))
  	    {
  	      cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond,
  								NULL,
  								false);
  	    }
  	}
*************** thread_across_edge (struct dom_walk_data
*** 674,680 ****
  	    cached_lhs = 0;
  	}
        else
! 	cached_lhs = lookup_avail_expr (stmt, NULL, false);
  
        if (cached_lhs)
  	{
--- 672,678 ----
  	    cached_lhs = 0;
  	}
        else
! 	cached_lhs = lookup_avail_expr (stmt, false);
  
        if (cached_lhs)
  	{
*************** dom_opt_initialize_block_local_data (str
*** 730,737 ****
       make sure we clear them before using them!  */
    if (recycled)
      {
-       gcc_assert (!bd->avail_exprs
- 		  || VARRAY_ACTIVE_SIZE (bd->avail_exprs) == 0);
        gcc_assert (!bd->const_and_copies
  		  || VARRAY_ACTIVE_SIZE (bd->const_and_copies) == 0);
        gcc_assert (!bd->nonzero_vars
--- 728,733 ----
*************** dom_opt_initialize_block (struct dom_wal
*** 753,758 ****
--- 749,758 ----
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "\n\nOptimizing block #%d\n\n", bb->index);
  
+   /* Push a marker on AVAIL_EXPRS_STACK so that we know how far to
unwind
+      when we finalize this blcok.  */
+   VARRAY_PUSH_TREE (avail_exprs_stack, NULL_TREE);
+ 
    record_equivalences_from_incoming_edge (walk_data, bb);
  
    /* PHI nodes can create equivalences too.  */
*************** initialize_hash_element (tree expr, tree
*** 805,826 ****
     LIMIT entries left in LOCALs.  */
  
  static void
! remove_local_expressions_from_table (varray_type locals,
! 				     unsigned limit,
! 				     htab_t table)
  {
-   if (! locals)
-     return;
- 
    /* Remove all the expressions made available in this block.  */
!   while (VARRAY_ACTIVE_SIZE (locals) > limit)
      {
        struct expr_hash_elt element;
!       tree expr = VARRAY_TOP_TREE (locals);
!       VARRAY_POP (locals);
  
        initialize_hash_element (expr, NULL, &element);
!       htab_remove_elt_with_hash (table, &element, element.hash);
      }
  }
  
--- 805,824 ----
     LIMIT entries left in LOCALs.  */
  
  static void
! remove_local_expressions_from_table (void)
  {
    /* Remove all the expressions made available in this block.  */
!   while (VARRAY_ACTIVE_SIZE (avail_exprs_stack) > 0)
      {
        struct expr_hash_elt element;
!       tree expr = VARRAY_TOP_TREE (avail_exprs_stack);
!       VARRAY_POP (avail_exprs_stack);
! 
!       if (expr == NULL_TREE)
! 	break;
  
        initialize_hash_element (expr, NULL, &element);
!       htab_remove_elt_with_hash (avail_exprs, &element, element.hash);
      }
  }
  
*************** dom_opt_finalize_block (struct dom_walk_
*** 953,976 ****
        if (get_immediate_dominator (CDI_DOMINATORS, true_edge->dest) !=
bb
  	  || phi_nodes (true_edge->dest))
  	{
- 	  unsigned avail_expr_limit;
  	  unsigned const_and_copies_limit;
  	  unsigned currdefs_limit;
  
- 	  avail_expr_limit
- 	    = bd->avail_exprs ? VARRAY_ACTIVE_SIZE (bd->avail_exprs) : 0;
  	  const_and_copies_limit
  	    = bd->const_and_copies ? VARRAY_ACTIVE_SIZE
(bd->const_and_copies)
  				   : 0;
  	  currdefs_limit
  	    = bd->block_defs ? VARRAY_ACTIVE_SIZE (bd->block_defs) : 0;
  
  	  /* Record any equivalences created by following this edge.  */
  	  if (TREE_CODE_CLASS (cond_code) == '<')
  	    {
! 	      record_cond (cond, boolean_true_node, &bd->avail_exprs);
! 	      record_dominating_conditions (cond, &bd->avail_exprs);
! 	      record_cond (inverted, boolean_false_node, &bd->avail_exprs);
  	    }
  	  else if (cond_code == SSA_NAME)
  	    record_const_or_copy (cond, boolean_true_node,
--- 951,976 ----
        if (get_immediate_dominator (CDI_DOMINATORS, true_edge->dest) !=
bb
  	  || phi_nodes (true_edge->dest))
  	{
  	  unsigned const_and_copies_limit;
  	  unsigned currdefs_limit;
  
  	  const_and_copies_limit
  	    = bd->const_and_copies ? VARRAY_ACTIVE_SIZE
(bd->const_and_copies)
  				   : 0;
  	  currdefs_limit
  	    = bd->block_defs ? VARRAY_ACTIVE_SIZE (bd->block_defs) : 0;
  
+ 	  /* Push a marker onto the available expression stack so that we
+ 	     unwind any expressions related to the TRUE arm before processing
+ 	     the false arm below.  */
+ 	  VARRAY_PUSH_TREE (avail_exprs_stack, NULL_TREE);
+ 
  	  /* Record any equivalences created by following this edge.  */
  	  if (TREE_CODE_CLASS (cond_code) == '<')
  	    {
! 	      record_cond (cond, boolean_true_node);
! 	      record_dominating_conditions (cond);
! 	      record_cond (inverted, boolean_false_node);
  	    }
  	  else if (cond_code == SSA_NAME)
  	    record_const_or_copy (cond, boolean_true_node,
*************** dom_opt_finalize_block (struct dom_walk_
*** 981,989 ****
  
  	  /* And restore the various tables to their state before
  	     we threaded this edge.  */
! 	  remove_local_expressions_from_table (bd->avail_exprs,
! 					       avail_expr_limit,
! 					       avail_exprs);
  	  restore_vars_to_original_value (bd->const_and_copies,
  					  const_and_copies_limit,
  					  const_and_copies);
--- 981,987 ----
  
  	  /* And restore the various tables to their state before
  	     we threaded this edge.  */
! 	  remove_local_expressions_from_table ();
  	  restore_vars_to_original_value (bd->const_and_copies,
  					  const_and_copies_limit,
  					  const_and_copies);
*************** dom_opt_finalize_block (struct dom_walk_
*** 997,1005 ****
  	  /* Record any equivalences created by following this edge.  */
  	  if (TREE_CODE_CLASS (cond_code) == '<')
  	    {
! 	      record_cond (cond, boolean_false_node, &bd->avail_exprs);
! 	      record_cond (inverted, boolean_true_node, &bd->avail_exprs);
! 	      record_dominating_conditions (inverted, &bd->avail_exprs);
  	    }
  	  else if (cond_code == SSA_NAME)
  	    record_const_or_copy (cond, boolean_false_node,
--- 995,1003 ----
  	  /* Record any equivalences created by following this edge.  */
  	  if (TREE_CODE_CLASS (cond_code) == '<')
  	    {
! 	      record_cond (cond, boolean_false_node);
! 	      record_cond (inverted, boolean_true_node);
! 	      record_dominating_conditions (inverted);
  	    }
  	  else if (cond_code == SSA_NAME)
  	    record_const_or_copy (cond, boolean_false_node,
*************** dom_opt_finalize_block (struct dom_walk_
*** 1013,1019 ****
  	}
      }
  
!   remove_local_expressions_from_table (bd->avail_exprs, 0,
avail_exprs);
    restore_nonzero_vars_to_original_value (bd->nonzero_vars, 0,
nonzero_vars);
    restore_vars_to_original_value (bd->const_and_copies, 0,
const_and_copies);
    restore_currdefs_to_original_value (bd->block_defs, 0);
--- 1011,1017 ----
  	}
      }
  
!   remove_local_expressions_from_table ();
    restore_nonzero_vars_to_original_value (bd->nonzero_vars, 0,
nonzero_vars);
    restore_vars_to_original_value (bd->const_and_copies, 0,
const_and_copies);
    restore_currdefs_to_original_value (bd->block_defs, 0);
*************** record_equivalences_from_incoming_edge (
*** 1228,1234 ****
        && (edge_flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
      eq_expr_value = get_eq_expr_value (parent_block_last_stmt,
  				       (edge_flags & EDGE_TRUE_VALUE) != 0,
- 				       &bd->avail_exprs,
  				       bb,
  				       &bd->vrp_variables);
    /* Similarly when the parent block ended in a SWITCH_EXPR.
--- 1226,1231 ----
*************** record_var_is_nonzero (tree var, varray_
*** 1358,1364 ****
     that the condition COND has the value VALUE.  */
  
  static void
! record_cond (tree cond, tree value, varray_type *block_avail_exprs_p)
  {
    struct expr_hash_elt *element = xmalloc (sizeof (struct
expr_hash_elt));
    void **slot;
--- 1355,1361 ----
     that the condition COND has the value VALUE.  */
  
  static void
! record_cond (tree cond, tree value)
  {
    struct expr_hash_elt *element = xmalloc (sizeof (struct
expr_hash_elt));
    void **slot;
*************** record_cond (tree cond, tree value, varr
*** 1370,1378 ****
    if (*slot == NULL)
      {
        *slot = (void *) element;
!       if (! *block_avail_exprs_p)
! 	VARRAY_TREE_INIT (*block_avail_exprs_p, 20, "block_avail_exprs");
!       VARRAY_PUSH_TREE (*block_avail_exprs_p, cond);
      }
    else
      free (element);
--- 1367,1373 ----
    if (*slot == NULL)
      {
        *slot = (void *) element;
!       VARRAY_PUSH_TREE (avail_exprs_stack, cond);
      }
    else
      free (element);
*************** record_cond (tree cond, tree value, varr
*** 1384,1390 ****
     For example, if a < b is true, then a <= b must also be true.  */
  
  static void
! record_dominating_conditions (tree cond, varray_type
*block_avail_exprs_p)
  {
    switch (TREE_CODE (cond))
      {
--- 1379,1385 ----
     For example, if a < b is true, then a <= b must also be true.  */
  
  static void
! record_dominating_conditions (tree cond)
  {
    switch (TREE_CODE (cond))
      {
*************** record_dominating_conditions (tree cond,
*** 1392,1437 ****
        record_cond (build2 (LE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (LTGT_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        break;
  
      case GT_EXPR:
        record_cond (build2 (GE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (LTGT_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        break;
  
      case GE_EXPR:
--- 1387,1424 ----
        record_cond (build2 (LE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (LTGT_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        break;
  
      case GT_EXPR:
        record_cond (build2 (GE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (LTGT_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        break;
  
      case GE_EXPR:
*************** record_dominating_conditions (tree cond,
*** 1439,1549 ****
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        break;
  
      case EQ_EXPR:
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (LE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (GE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        break;
  
      case UNORDERED_EXPR:
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (UNLE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (UNGE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (UNEQ_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (UNLT_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (UNGT_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        break;
  
      case UNLT_EXPR:
        record_cond (build2 (UNLE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        break;
  
      case UNGT_EXPR:
        record_cond (build2 (UNGE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        break;
  
      case UNEQ_EXPR:
        record_cond (build2 (UNLE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (UNGE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        break;
  
      case LTGT_EXPR:
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node,
! 		   block_avail_exprs_p);
  
      default:
        break;
--- 1426,1518 ----
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        break;
  
      case EQ_EXPR:
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (LE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (GE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        break;
  
      case UNORDERED_EXPR:
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (UNLE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (UNGE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (UNEQ_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (UNLT_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (UNGT_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        break;
  
      case UNLT_EXPR:
        record_cond (build2 (UNLE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        break;
  
      case UNGT_EXPR:
        record_cond (build2 (UNGE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        break;
  
      case UNEQ_EXPR:
        record_cond (build2 (UNLE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (UNGE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        break;
  
      case LTGT_EXPR:
        record_cond (build2 (NE_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
        record_cond (build2 (ORDERED_EXPR, boolean_type_node,
  			   TREE_OPERAND (cond, 0),
  			   TREE_OPERAND (cond, 1)),
! 		   boolean_true_node);
  
      default:
        break;
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1638,1645 ****
    tree rhs = TREE_OPERAND (stmt, 1);
    enum tree_code rhs_code = TREE_CODE (rhs);
    tree result = NULL;
-   struct dom_walk_block_data *bd
-     = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
  
    /* If we have lhs = ~x, look and see if we earlier had x = ~y.
       In which case we can change this statement to be lhs = y.
--- 1607,1612 ----
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1665,1671 ****
  	      && ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs_def_operand))
  	    result = update_rhs_and_lookup_avail_expr (stmt,
  						       rhs_def_operand,
- 						       &bd->avail_exprs,
  						       insert);
  	}
      }
--- 1632,1637 ----
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1749,1756 ****
  			   || TREE_CODE_CLASS (TREE_CODE (t)) == '<')
  			  && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
  			  && is_gimple_val (TREE_OPERAND (t, 1))))
! 		    result = update_rhs_and_lookup_avail_expr
! 		      (stmt, t, &bd->avail_exprs, insert);
  		}
  	    }
  	}
--- 1715,1721 ----
  			   || TREE_CODE_CLASS (TREE_CODE (t)) == '<')
  			  && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
  			  && is_gimple_val (TREE_OPERAND (t, 1))))
! 		    result = update_rhs_and_lookup_avail_expr (stmt, t, insert);
  		}
  	    }
  	}
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1790,1798 ****
  	      TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 1)
  		= integer_zero_node;
  	    }
! 	  val = simplify_cond_and_lookup_avail_expr (dummy_cond,
! 						     &bd->avail_exprs,
! 						     NULL, false);
  	}
  
        if (val && integer_onep (val))
--- 1755,1761 ----
  	      TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 1)
  		= integer_zero_node;
  	    }
! 	  val = simplify_cond_and_lookup_avail_expr (dummy_cond, NULL,
false);
  	}
  
        if (val && integer_onep (val))
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1809,1816 ****
  		       local_fold (build (MINUS_EXPR, TREE_TYPE (op1),
  					  op1, integer_one_node)));
  
! 	  result = update_rhs_and_lookup_avail_expr (stmt, t,
! 						     &bd->avail_exprs, insert);
  	}
      }
  
--- 1772,1778 ----
  		       local_fold (build (MINUS_EXPR, TREE_TYPE (op1),
  					  op1, integer_one_node)));
  
! 	  result = update_rhs_and_lookup_avail_expr (stmt, t, insert);
  	}
      }
  
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1845,1853 ****
  	      TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 1)
  		= build_int_cst (type, 0);
  	    }
! 	  val = simplify_cond_and_lookup_avail_expr (dummy_cond,
! 						     &bd->avail_exprs,
! 						     NULL, false);
  
  	  if (!val)
  	    {
--- 1807,1813 ----
  	      TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 1)
  		= build_int_cst (type, 0);
  	    }
! 	  val = simplify_cond_and_lookup_avail_expr (dummy_cond, NULL,
false);
  
  	  if (!val)
  	    {
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1857,1863 ****
  		= build_int_cst (type, 0);
  
  	      val = simplify_cond_and_lookup_avail_expr (dummy_cond,
- 							 &bd->avail_exprs,
  							 NULL, false);
  
  	      if (val)
--- 1817,1822 ----
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1880,1887 ****
  	  else
  	    t = op;
  
! 	  result = update_rhs_and_lookup_avail_expr (stmt, t,
! 						     &bd->avail_exprs, insert);
  	}
      }
  
--- 1839,1845 ----
  	  else
  	    t = op;
  
! 	  result = update_rhs_and_lookup_avail_expr (stmt, t, insert);
  	}
      }
  
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1892,1899 ****
        tree t = fold_read_from_constant_string (rhs);
  
        if (t)
!         result = update_rhs_and_lookup_avail_expr (stmt, t,
! 						   &bd->avail_exprs, insert);
      }
  
    return result;
--- 1850,1856 ----
        tree t = fold_read_from_constant_string (rhs);
  
        if (t)
!         result = update_rhs_and_lookup_avail_expr (stmt, t, insert);
      }
  
    return result;
*************** find_equivalent_equality_comparison (tre
*** 1968,1974 ****
  
  static tree
  simplify_cond_and_lookup_avail_expr (tree stmt,
- 				     varray_type *block_avail_exprs_p,
  				     stmt_ann_t ann,
  				     int insert)
  {
--- 1925,1930 ----
*************** simplify_cond_and_lookup_avail_expr (tre
*** 2008,2015 ****
  
  		  /* Lookup the condition and return its known value if it
  		     exists.  */
! 		  new_cond = lookup_avail_expr (stmt, block_avail_exprs_p,
! 						insert);
  		  if (new_cond)
  		    return new_cond;
  
--- 1964,1970 ----
  
  		  /* Lookup the condition and return its known value if it
  		     exists.  */
! 		  new_cond = lookup_avail_expr (stmt, insert);
  		  if (new_cond)
  		    return new_cond;
  
*************** simplify_cond_and_lookup_avail_expr (tre
*** 2198,2206 ****
     condition which we may be able to optimize better.  */
  
  static tree
! simplify_switch_and_lookup_avail_expr (tree stmt,
! 				       varray_type *block_avail_exprs_p,
! 				       int insert)
  {
    tree cond = SWITCH_COND (stmt);
    tree def, to, ti;
--- 2153,2159 ----
     condition which we may be able to optimize better.  */
  
  static tree
! simplify_switch_and_lookup_avail_expr (tree stmt, int insert)
  {
    tree cond = SWITCH_COND (stmt);
    tree def, to, ti;
*************** simplify_switch_and_lookup_avail_expr (t
*** 2246,2252 ****
  		  SWITCH_COND (stmt) = def;
  		  modify_stmt (stmt);
  
! 		  return lookup_avail_expr (stmt, block_avail_exprs_p, insert);
  		}
  	    }
  	}
--- 2199,2205 ----
  		  SWITCH_COND (stmt) = def;
  		  modify_stmt (stmt);
  
! 		  return lookup_avail_expr (stmt, insert);
  		}
  	    }
  	}
*************** eliminate_redundant_computations (struct
*** 2378,2385 ****
    bool insert = true;
    tree cached_lhs;
    bool retval = false;
-   struct dom_walk_block_data *bd
-     = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
  
    if (TREE_CODE (stmt) == MODIFY_EXPR)
      def = TREE_OPERAND (stmt, 0);
--- 2331,2336 ----
*************** eliminate_redundant_computations (struct
*** 2394,2421 ****
      insert = false;
  
    /* Check if the expression has been computed before.  */
!   cached_lhs = lookup_avail_expr (stmt, &bd->avail_exprs, insert);
  
    /* If this is an assignment and the RHS was not in the hash table,
       then try to simplify the RHS and lookup the new RHS in the
       hash table.  */
    if (! cached_lhs && TREE_CODE (stmt) == MODIFY_EXPR)
!     cached_lhs = simplify_rhs_and_lookup_avail_expr (walk_data,
! 						     stmt,
! 						     insert);
    /* Similarly if this is a COND_EXPR and we did not find its
       expression in the hash table, simplify the condition and
       try again.  */
    else if (! cached_lhs && TREE_CODE (stmt) == COND_EXPR)
!     cached_lhs = simplify_cond_and_lookup_avail_expr (stmt,
! 						      &bd->avail_exprs,
! 						      ann,
! 						      insert);
    /* Similarly for a SWITCH_EXPR.  */
    else if (!cached_lhs && TREE_CODE (stmt) == SWITCH_EXPR)
!     cached_lhs = simplify_switch_and_lookup_avail_expr (stmt,
! 						        &bd->avail_exprs,
! 						        insert);
  
    opt_stats.num_exprs_considered++;
  
--- 2345,2365 ----
      insert = false;
  
    /* Check if the expression has been computed before.  */
!   cached_lhs = lookup_avail_expr (stmt, insert);
  
    /* If this is an assignment and the RHS was not in the hash table,
       then try to simplify the RHS and lookup the new RHS in the
       hash table.  */
    if (! cached_lhs && TREE_CODE (stmt) == MODIFY_EXPR)
!     cached_lhs = simplify_rhs_and_lookup_avail_expr (walk_data, stmt,
insert);
    /* Similarly if this is a COND_EXPR and we did not find its
       expression in the hash table, simplify the condition and
       try again.  */
    else if (! cached_lhs && TREE_CODE (stmt) == COND_EXPR)
!     cached_lhs = simplify_cond_and_lookup_avail_expr (stmt, ann,
insert);
    /* Similarly for a SWITCH_EXPR.  */
    else if (!cached_lhs && TREE_CODE (stmt) == SWITCH_EXPR)
!     cached_lhs = simplify_switch_and_lookup_avail_expr (stmt, insert);
  
    opt_stats.num_exprs_considered++;
  
*************** eliminate_redundant_computations (struct
*** 2471,2477 ****
  
  static void
  record_equivalences_from_stmt (tree stmt,
- 			       varray_type *block_avail_exprs_p,
  			       varray_type *block_nonzero_vars_p,
  			       int may_optimize_p,
  			       stmt_ann_t ann)
--- 2415,2420 ----
*************** record_equivalences_from_stmt (tree stmt
*** 2598,2604 ****
  
  	  /* Finally enter the statement into the available expression
  	     table.  */
! 	  lookup_avail_expr (new, block_avail_exprs_p, true);
  	}
      }
  }
--- 2541,2547 ----
  
  	  /* Finally enter the statement into the available expression
  	     table.  */
! 	  lookup_avail_expr (new, true);
  	}
      }
  }
*************** optimize_stmt (struct dom_walk_data *wal
*** 2803,2809 ****
    /* Record any additional equivalences created by this statement.  */
    if (TREE_CODE (stmt) == MODIFY_EXPR)
      record_equivalences_from_stmt (stmt,
- 				   &bd->avail_exprs,
  				   &bd->nonzero_vars,
  				   may_optimize_p,
  				   ann);
--- 2746,2751 ----
*************** optimize_stmt (struct dom_walk_data *wal
*** 2870,2878 ****
     hash table to account for the changes made to STMT.  */
  
  static tree
! update_rhs_and_lookup_avail_expr (tree stmt, tree new_rhs, 
! 				  varray_type *block_avail_exprs_p,
! 				  bool insert)
  {
    tree cached_lhs = NULL;
  
--- 2812,2818 ----
     hash table to account for the changes made to STMT.  */
  
  static tree
! update_rhs_and_lookup_avail_expr (tree stmt, tree new_rhs, bool
insert)
  {
    tree cached_lhs = NULL;
  
*************** update_rhs_and_lookup_avail_expr (tree s
*** 2889,2895 ****
    TREE_OPERAND (stmt, 1) = new_rhs;
  
    /* Now lookup the updated statement in the hash table.  */
!   cached_lhs = lookup_avail_expr (stmt, block_avail_exprs_p, insert);
  
    /* We have now called lookup_avail_expr twice with two different
       versions of this same statement, once in optimize_stmt, once
here.
--- 2829,2835 ----
    TREE_OPERAND (stmt, 1) = new_rhs;
  
    /* Now lookup the updated statement in the hash table.  */
!   cached_lhs = lookup_avail_expr (stmt, insert);
  
    /* We have now called lookup_avail_expr twice with two different
       versions of this same statement, once in optimize_stmt, once
here.
*************** update_rhs_and_lookup_avail_expr (tree s
*** 2913,2919 ****
       we found a copy of this statement in the second hash table lookup
       we want _no_ copies of this statement in BLOCK_AVAIL_EXPRs.  */
    if (insert)
!     VARRAY_POP (*block_avail_exprs_p);
  
    /* And make sure we record the fact that we modified this
       statement.  */
--- 2853,2859 ----
       we found a copy of this statement in the second hash table lookup
       we want _no_ copies of this statement in BLOCK_AVAIL_EXPRs.  */
    if (insert)
!     VARRAY_POP (avail_exprs_stack);
  
    /* And make sure we record the fact that we modified this
       statement.  */
*************** update_rhs_and_lookup_avail_expr (tree s
*** 2935,2941 ****
     aliased references.  */
  
  static tree
! lookup_avail_expr (tree stmt, varray_type *block_avail_exprs_p, bool
insert)
  {
    void **slot;
    tree lhs;
--- 2875,2881 ----
     aliased references.  */
  
  static tree
! lookup_avail_expr (tree stmt, bool insert)
  {
    void **slot;
    tree lhs;
*************** lookup_avail_expr (tree stmt, varray_typ
*** 2989,2997 ****
    if (*slot == NULL)
      {
        *slot = (void *) element;
!       if (! *block_avail_exprs_p)
!         VARRAY_TREE_INIT (*block_avail_exprs_p, 20,
"block_avail_exprs");
!       VARRAY_PUSH_TREE (*block_avail_exprs_p, stmt ? stmt :
element->rhs);
        return NULL_TREE;
      }
  
--- 2929,2935 ----
    if (*slot == NULL)
      {
        *slot = (void *) element;
!       VARRAY_PUSH_TREE (avail_exprs_stack, stmt ? stmt :
element->rhs);
        return NULL_TREE;
      }
  
*************** record_range (tree cond, basic_block bb,
*** 3134,3140 ****
  static struct eq_expr_value
  get_eq_expr_value (tree if_stmt,
  		   int true_arm,
- 		   varray_type *block_avail_exprs_p,
  		   basic_block bb,
  		   varray_type *vrp_variables_p)
  {
--- 3072,3077 ----
*************** get_eq_expr_value (tree if_stmt,
*** 3200,3208 ****
  	     condition into the hash table.  */
  	  if (true_arm)
  	    {
! 	      record_cond (cond, boolean_true_node, block_avail_exprs_p);
! 	      record_dominating_conditions (cond, block_avail_exprs_p);
! 	      record_cond (inverted, boolean_false_node,
block_avail_exprs_p);
  
  	      if (TREE_CONSTANT (op1))
  		record_range (cond, bb, vrp_variables_p);
--- 3137,3145 ----
  	     condition into the hash table.  */
  	  if (true_arm)
  	    {
! 	      record_cond (cond, boolean_true_node);
! 	      record_dominating_conditions (cond);
! 	      record_cond (inverted, boolean_false_node);
  
  	      if (TREE_CONSTANT (op1))
  		record_range (cond, bb, vrp_variables_p);
*************** get_eq_expr_value (tree if_stmt,
*** 3219,3227 ****
  	  else
  	    {
  
! 	      record_cond (inverted, boolean_true_node, block_avail_exprs_p);
! 	      record_dominating_conditions (inverted, block_avail_exprs_p);
! 	      record_cond (cond, boolean_false_node, block_avail_exprs_p);
  
  	      if (TREE_CONSTANT (op1))
  		record_range (inverted, bb, vrp_variables_p);
--- 3156,3164 ----
  	  else
  	    {
  
! 	      record_cond (inverted, boolean_true_node);
! 	      record_dominating_conditions (inverted);
! 	      record_cond (cond, boolean_false_node);
  
  	      if (TREE_CONSTANT (op1))
  		record_range (inverted, bb, vrp_variables_p);



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