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]

[tree-ssa]: Keep SSA info up to date in SSAPRE


Bootstrapped on powerpc and x86.
Committed.

Doesn't handle strength reduction injuries yet.

2002-09-26 Daniel Berlin <dberlin@dberlin.org>

* tree-ssa-pre.c (update_phis_in_list): New function.
(update_ssa_for_new_use): New function.
(code_motion): Start working on code to update SSA representation.
(find_reaching_def_of_var): New function.

Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-pre.c,v
retrieving revision 1.1.4.20
diff -c -3 -p -w -B -b -r1.1.4.20 tree-ssa-pre.c
*** tree-ssa-pre.c 23 Sep 2002 13:22:14 -0000 1.1.4.20
--- tree-ssa-pre.c 26 Sep 2002 18:56:38 -0000
*************** Boston, MA 02111-1307, USA. */
*** 49,55 ****
#include "tree-inline.h"

#define EXTRANEOUS_EPHI_REMOVAL 0
! #define DEBUGGING_STRRED 1
/* See http://citeseer.nj.nec.com/chow97new.html, and
http://citeseer.nj.nec.com/kennedy99partial.html for details of the
algorithm.
--- 49,57 ----
#include "tree-inline.h"

#define EXTRANEOUS_EPHI_REMOVAL 0
! #define DEBUGGING_STRRED 0
! #define DEBUGGING_SSA_UPDATE 0
!
/* See http://citeseer.nj.nec.com/chow97new.html, and
http://citeseer.nj.nec.com/kennedy99partial.html for details of the
algorithm.
*************** static tree calculate_increment PARAMS (
*** 116,121 ****
--- 118,127 ----
static void repair_injury PARAMS ((struct expr_info *, tree_ref, tree));
static void set_need_repair PARAMS ((struct expr_info *, tree_ref));
static void calculate_preorder PARAMS ((void));
+ static void update_phis_in_list PARAMS ((ref_list, tree_ref, tree_ref));
+ static void update_ssa_for_new_use PARAMS ((tree, tree, tree_ref, basic_block));
+ static int find_reaching_def_of_var PARAMS ((tree_ref, basic_block, tree_ref));
+
static int *pre_preorder;
static dominance_info pre_idom;
static sbitmap *pre_dfs;
*************** static int preorder_count;
*** 126,131 ****
--- 132,139 ----
/*FIXME: Move into expr_info or make them go away. */
static tree_ref *avdefs;
static splay_tree orig_expr_map;
+ static splay_tree new_stmt_map;
+
static splay_tree need_repair_map;
static bool strred_candidate;

*************** finalize_1 (ei, temp)
*** 1420,1425 ****
--- 1427,1435 ----
tree expr;
basic_block bb;
tree endtree;
+ struct ref_list_node *tmp;
+ tree_ref tempref;
+
/* Insert definition of expr at end of BB containing X. */
if (dump_file)
{
*************** finalize_1 (ei, temp)
*** 1429,1440 ****
fprintf (dump_file, " to ");
print_c_tree (dump_file, temp);
fprintf (dump_file, " after ");
! print_c_node (dump_file, BLOCK_END_TREE (ref_bb(X)->index));
! fprintf (dump_file, " (at end of BB), because of ExprPhi");
fprintf (dump_file, " in BB %d\n",
ref_bb (phi)->index);
}
! expr = fold (build_modify_expr (temp, NOP_EXPR, ei->expr));
stmt = build_stmt (EXPR_STMT, expr);
TREE_TYPE (stmt) = TREE_TYPE (expr);
bb = ref_bb (X);
--- 1439,1453 ----
fprintf (dump_file, " to ");
print_c_tree (dump_file, temp);
fprintf (dump_file, " after ");
! print_c_node (dump_file,
! BLOCK_END_TREE (ref_bb(X)->index));
! fprintf (dump_file,
! " (at end of BB), because of ExprPhi");
fprintf (dump_file, " in BB %d\n",
ref_bb (phi)->index);
}
! expr = fold (build_modify_expr (temp, NOP_EXPR,
! deep_copy_node (ei->expr)));
stmt = build_stmt (EXPR_STMT, expr);
TREE_TYPE (stmt) = TREE_TYPE (expr);
bb = ref_bb (X);
*************** finalize_1 (ei, temp)
*** 1442,1447 ****
--- 1455,1485 ----
This might not be necessary once goto elimination
is functional. */
endtree = BLOCK_END_TREE (bb->index);
+ /* Update the SSA for the newly inserted definition.
+ This is a phi operand occurrence insertion, so we know
+ *something* caused one or more variables in our expression
+ to be modified in this block.
+ We can find the definitions of the modified variables by
+ finding the real phis for each variable (if one exists),
+ which will be in the ephi's basic block.
+ We can find the definitions of non-modified variables
+ by walking back up the dominator tree, seeing if we have a
+ def or use of the variable in that bb, and getting it from
+ that.
+
+ */
+ find_refs_in_stmt (stmt, bb);
+ FOR_EACH_REF (tempref, tmp, tree_refs (stmt))
+ {
+ if (!(ref_type (tempref) & V_USE))
+ continue;
+ find_reaching_def_of_var (tempref, bb, phi);
+ }
+
+ splay_tree_insert (new_stmt_map,
+ (splay_tree_key) expr,
+ (splay_tree_value) stmt);
+
if (is_ctrl_altering_stmt (endtree))
insert_stmt_tree_before (stmt, endtree, bb);
else
*************** calculate_increment (ei, expr)
*** 1817,1826 ****
abort();
/*XXX: Currently assume it's a * <constant>, thus this will give us
constant. */
! incr = build_binary_op (MULT_EXPR, incr, TREE_OPERAND (ei->expr, 1), 1);
#if DEBUGGING_STRRED
! fprintf (stderr, "Increment calculated to be: ");
! debug_c_tree (incr);
#endif
return incr;

--- 1855,1868 ----
abort();
/*XXX: Currently assume it's a * <constant>, thus this will give us
constant. */
! incr = fold (build (MULT_EXPR, TREE_TYPE (ei->expr),
! incr, TREE_OPERAND (ei->expr, 1)));
#if DEBUGGING_STRRED
! if (dump_file)
! {
! fprintf (dump_file, "Increment calculated to be: ");
! print_c_tree (dump_file, incr);
! }
#endif
return incr;

*************** repair_injury (ei, use, temp)
*** 1854,1865 ****
if (htab_find (ei->repaired, ref_expr (v)) == NULL)
{
#if DEBUGGING_STRRED
! fprintf (stderr, "Injuring def to repair is: ");
! debug_c_tree (ref_expr (v));
#endif
incr = calculate_increment (ei, ref_expr (v));
! expr = build_modify_expr (temp, NOP_EXPR, build_binary_op
! (PLUS_EXPR, temp, incr, 0));
stmt = build_stmt (EXPR_STMT, expr);
TREE_TYPE (stmt) = TREE_TYPE (expr);
bb = ref_bb (use);
--- 1896,1912 ----
if (htab_find (ei->repaired, ref_expr (v)) == NULL)
{
#if DEBUGGING_STRRED
! if (dump_file)
! {
! fprintf (dump_file, "Injuring def to repair is: ");
! print_c_tree (dump_file, ref_expr (v));
! }
#endif
incr = calculate_increment (ei, ref_expr (v));
! expr = build_modify_expr (temp, NOP_EXPR,
! fold (build (PLUS_EXPR,
! TREE_TYPE (temp),
! temp, incr)));
stmt = build_stmt (EXPR_STMT, expr);
TREE_TYPE (stmt) = TREE_TYPE (expr);
bb = ref_bb (use);
*************** repair_injury (ei, use, temp)
*** 1901,1913 ****
{

#if DEBUGGING_STRRED
! fprintf (stderr, "Injuring def to repair is: ");
! debug_c_node (ref_expr (imm_reaching_def (v)));
#endif
incr = calculate_increment (ei,
ref_expr (imm_reaching_def (v)));
! expr = build_modify_expr (temp, NOP_EXPR, build_binary_op
! (PLUS_EXPR, temp, incr, 0));
stmt = build_stmt (EXPR_STMT, expr);
TREE_TYPE (stmt) = TREE_TYPE (expr);
bb = ref_bb (use);
--- 1948,1966 ----
{

#if DEBUGGING_STRRED
! if (dump_file)
! {
! fprintf (dump_file, "Injuring def to repair is: ");
! print_c_node (dump_file,ref_expr (imm_reaching_def (v)));
! }
!
#endif
incr = calculate_increment (ei,
ref_expr (imm_reaching_def (v)));
! expr = build_modify_expr (temp, NOP_EXPR,
! fold (build (PLUS_EXPR,
! TREE_TYPE (temp),
! temp, incr)));
stmt = build_stmt (EXPR_STMT, expr);
TREE_TYPE (stmt) = TREE_TYPE (expr);
bb = ref_bb (use);
*************** repair_injury (ei, use, temp)
*** 1933,1938 ****
--- 1986,2212 ----
}
}

+ /* Given a VAR reference, a basic block to look in (STMTBB), and optionally, a
+ ePHI that is for the expression containing the variable, find and set the
+ immediate reaching definition of VAR. */
+ static int
+ find_reaching_def_of_var (var, stmtbb, phi)
+ tree_ref var;
+ basic_block stmtbb;
+ tree_ref phi;
+ {
+ tree_ref tempref;
+ struct ref_list_node *tmp;
+
+ if (phi)
+ FOR_EACH_REF (tempref, tmp, bb_refs (ref_bb (phi)))
+ {
+ if (!(ref_type (tempref) & V_PHI))
+ continue;
+ if (ref_var (tempref) == ref_var (var))
+ {
+ int opnum;
+ phi_node_arg realphiarg;
+
+ opnum = opnum_of_phi (tempref, stmtbb->index);
+ realphiarg = VARRAY_GENERIC_PTR (phi_args (tempref), opnum);
+
+ set_imm_reaching_def (var, phi_arg_def (realphiarg));
+ add_ref_to_list_end (imm_uses (phi_arg_def (realphiarg)), var);
+
+ return 1;
+ }
+ }
+ FOR_EACH_REF_REV (tempref, tmp, bb_refs (stmtbb))
+ {
+ if (!(ref_type (tempref) & (V_DEF | V_USE)) || tempref == var)
+ continue;
+ if (ref_var (tempref) == ref_var (var))
+ {
+ if (ref_type (tempref) & V_USE)
+ {
+ set_imm_reaching_def (var, imm_reaching_def (tempref));
+ add_ref_to_list_end (imm_uses (imm_reaching_def (tempref)), var);
+ }
+ else
+ {
+ set_imm_reaching_def (var, tempref);
+ add_ref_to_list_end (imm_uses (tempref), var);
+ }
+
+ return 1;
+ }
+ }
+ return find_reaching_def_of_var (var,
+ get_immediate_dominator (pre_idom, stmtbb),
+ NULL);
+ }
+
+ /* Update the SSA representation to account for the new use of the temporary
+ TEMP in NEWUSE, located in BB.
+ This *actually* modifies the trees, so that newuse will be a use of the
+ temporary, instead of the expression it is now. */
+ static void
+ update_ssa_for_new_use (temp, newuse, defby, bb)
+ tree temp;
+ tree newuse;
+ tree_ref defby;
+ basic_block bb;
+
+ {
+ tree_ref tempref;
+ struct ref_list_node *tmp;
+ splay_tree_node orignode, reachingnode;
+ tree_ref use_orig_ref;
+ tree_ref olddefref, newdefref, newuseref;
+ tree reachingstmt;
+ ref_list todelete = create_ref_list ();
+ ref_list reachedtoadd = create_ref_list ();
+ ref_list immtoadd = create_ref_list ();
+
+ /* Update the SSA info for the new use of the temporary.
+ Complex process to do so.
+ 1. Delete the uses in the expression we are replacing with
+ a use of the temporary, from all the lists they might
+ appear in.
+ 2. Make a copy of the reached uses/immediate uses of the def
+ in the expression.
+ 3. Delete the def (It's easier to redo it than update it) in
+ the expression.
+ 4. Do the actual expression replacement.
+ 5. Create a new def for the expression, move the old immediate
+ defs and uses.
+ 6. Update the arguments of any phis reached by the old def,
+ that point to the old def, to point to the new def.
+ 7. Create a new use for the temporary, with a reaching def
+ of the def of the assignment expression we just created for
+ this save.
+
+ This is a bit simplified, since when i update a reaching def, we update the
+ reaching def's immediate uses, etc.
+ */
+
+ orignode = splay_tree_lookup (orig_expr_map, (splay_tree_key) newuse);
+ FOR_EACH_REF (tempref, tmp, tree_refs ((tree)orignode->value))
+ {
+ if (ref_type (tempref) & V_DEF)
+ {
+ use_orig_ref = tempref;
+ break;
+ }
+ }
+ olddefref = find_def_for_stmt (ref_stmt (use_orig_ref));
+ FOR_EACH_REF (tempref, tmp, tree_refs (ref_expr (use_orig_ref)))
+ {
+ remove_ref_from_list (tree_refs (ref_stmt (use_orig_ref)),
+ tempref);
+ if (ref_type (tempref) & V_DEF)
+ {
+ add_list_to_list_end (immtoadd, imm_uses (tempref));
+ add_list_to_list_end (reachedtoadd,
+ reached_uses (tempref));
+ }
+ if (!(ref_type (tempref) & V_USE))
+ continue;
+ remove_tree_ref (ref_var (tempref), tempref);
+ remove_bb_ref (bb, tempref);
+ if (imm_reaching_def (tempref) != NULL)
+ {
+ tree_ref rdef = imm_reaching_def (tempref);
+
+ remove_ref_from_list (imm_uses (rdef), tempref);
+ remove_ref_from_list (reached_uses (rdef), tempref);
+ }
+ add_ref_to_list_end (todelete, tempref);
+ }
+
+ FOR_EACH_REF (tempref, tmp, todelete)
+ {
+ remove_tree_ref (ref_expr (use_orig_ref), tempref);
+ }
+ remove_tree_ann (ref_expr (use_orig_ref));
+ replace_expr_in_tree (ref_stmt (use_orig_ref), newuse, temp);
+ newdefref = create_ref (TREE_OPERAND (ref_expr (use_orig_ref), 0),
+ V_DEF, bb, ref_stmt (use_orig_ref),
+ ref_expr (use_orig_ref),
+ &TREE_OPERAND (ref_expr (use_orig_ref), 0),
+ true);
+ add_list_to_list_end (reached_uses (newdefref), reachedtoadd);
+ add_list_to_list_end (imm_uses (newdefref), immtoadd);
+
+ update_phis_in_list (reached_uses (newdefref), olddefref, newdefref);
+ update_phis_in_list (imm_uses (newdefref), olddefref, newdefref);
+
+ newuseref = create_ref (temp, V_USE, bb, ref_stmt (use_orig_ref),
+ ref_expr (use_orig_ref),
+ find_expr_in_tree (ref_expr (use_orig_ref), temp),
+ true);
+ if (! (ref_type (defby) & E_PHI))
+ {
+ /* For non-PHI's we created, the map is euse expression -> new pretmp
+ save stmt. */
+ reachingnode = splay_tree_lookup (new_stmt_map,
+ (splay_tree_key) ref_expr (defby));
+ if (!reachingnode)
+ abort();
+ reachingstmt = (tree) reachingnode->value;
+
+ set_imm_reaching_def (newuseref, find_def_for_stmt (reachingstmt));
+ add_ref_to_list_end (reached_uses (find_def_for_stmt (reachingstmt)),
+ newuseref);
+ add_ref_to_list_end (imm_uses (find_def_for_stmt (reachingstmt)),
+ newuseref);
+ }
+ else
+ {
+ /* For PHI nodes we create, the map is ephi -> inserted phi.
+ it. */
+ tree_ref reachingphi;
+ reachingnode = splay_tree_lookup (new_stmt_map,
+ (splay_tree_key) defby);
+ if (!reachingnode)
+ abort();
+
+ reachingphi = (tree_ref) reachingnode->value;
+ set_imm_reaching_def (newuseref, reachingphi);
+ add_ref_to_list_end (reached_uses (reachingphi), newuseref);
+ add_ref_to_list_end (imm_uses (reachingphi), newuseref);
+ }
+
+
+ delete_ref_list (todelete);
+ delete_ref_list (reachedtoadd);
+ delete_ref_list (immtoadd);
+
+ }
+
+
+
+ /* Update all the phi argument definitions in REFS so that arguments defined by
+ OLD are now defined by NEW. */
+ static void
+ update_phis_in_list (refs, old, new)
+ ref_list refs;
+ tree_ref old;
+ tree_ref new;
+ {
+ size_t i;
+ struct ref_list_node *tmp;
+ tree_ref tempref;
+
+ FOR_EACH_REF (tempref, tmp, refs)
+ {
+ if (!(ref_type (tempref) & V_PHI))
+ continue;
+
+ for (i = 0; i < VARRAY_ACTIVE_SIZE (phi_args (tempref)); i++)
+ {
+ if (phi_arg_def (phi_arg (tempref, i)) == old)
+ phi_arg (tempref, i)->def = new;
+ }
+ }
+ }
+
/* Perform actual code motion. */
static void
code_motion (ei, temp)
*************** code_motion (ei, temp)
*** 1963,1968 ****
--- 2237,2245 ----
insert_euse_in_preorder_dt_order (ei, exprs);
while (!fibheap_empty (exprs))
{
+ struct ref_list_node *tmp;
+ tree_ref tempref;
+
use = fibheap_extract_min (exprs);
if (ref_type (use) & E_USE /*&& !EXPRUSE_PHIOP (use) */
&& !exprref_inserted (use))
*************** code_motion (ei, temp)
*** 1975,1981 ****
basic_block use_bb = ref_bb (use);
tree use_stmt = ref_stmt (use);
tree use_expr = ref_expr (use);
! tree newexpr;
if (dump_file)
{
fprintf (dump_file, "In BB %d, insert save of ",
--- 2252,2277 ----
basic_block use_bb = ref_bb (use);
tree use_stmt = ref_stmt (use);
tree use_expr = ref_expr (use);
! tree_ref use_orig_ref = NULL;
! tree newexpr, newstmt;
!
! splay_tree_node orignode;
! orignode =
! splay_tree_lookup (orig_expr_map, (splay_tree_key) use_expr);
! if (!orignode)
! abort();
!
! FOR_EACH_REF (tempref, tmp, tree_refs ((tree)orignode->value))
! {
! if (ref_type (tempref) & V_DEF)
! {
! use_orig_ref = tempref;
! break;
! }
! }
!
! if (!use_orig_ref)
! abort();
if (dump_file)
{
fprintf (dump_file, "In BB %d, insert save of ",
*************** code_motion (ei, temp)
*** 1987,1996 ****
print_c_tree (dump_file, TREE_OPERAND (use_stmt, 0));
fprintf (dump_file, " on line %d\n", STMT_LINENO (use_stmt));
}
! newexpr = fold (build_modify_expr (temp, NOP_EXPR, use_expr));
! insert_stmt_tree_before (build_stmt (EXPR_STMT, newexpr),
! use_stmt, use_bb);
! replace_expr_in_tree (use_stmt, use_expr, temp);
}
else if (exprref_reload (use))
{
--- 2283,2324 ----
print_c_tree (dump_file, TREE_OPERAND (use_stmt, 0));
fprintf (dump_file, " on line %d\n", STMT_LINENO (use_stmt));
}
! newexpr = fold (build_modify_expr (temp, NOP_EXPR,
! deep_copy_node (use_expr)));
! newstmt = build_stmt (EXPR_STMT, newexpr);
! /* Update the SSA representation for the new def of the
! temporary.
! 1. Create the defs and uses for the new statement.
! 2. Copy the reaching def from the old uses (in the assignment
! expression we are going to replace with the temporary next).
! */
! find_refs_in_stmt (newstmt, use_bb);
!
! FOR_EACH_REF (tempref, tmp, tree_refs (newexpr))
! {
! tree_ref olddef;
! if (!(ref_type (tempref) & V_USE))
! continue;
!
! olddef = find_use_for_var (use_expr, ref_var (tempref));
! olddef = imm_reaching_def (olddef);
!
! set_imm_reaching_def (tempref, olddef);
! }
!
! insert_stmt_tree_before (newstmt, use_stmt, use_bb);
! splay_tree_insert (new_stmt_map,
! (splay_tree_key) ref_expr (use),
! (splay_tree_value) newstmt);
! update_ssa_for_new_use (temp, ref_expr (use), use, use_bb);
! #if DEBUGGING_SSA_UPDATE
! if (dump_file)
! {
! fprintf (dump_file, "\nUpdated a save use:\n");
! dump_ref_list (dump_file, "", tree_refs (use_stmt), 0, 0);
! }
! #endif
!
}
else if (exprref_reload (use))
{
*************** code_motion (ei, temp)
*** 2008,2015 ****
print_c_tree (dump_file, TREE_OPERAND (use_stmt, 0));
fprintf (dump_file, " on line %d\n", STMT_LINENO (use_stmt));
}
! replace_expr_in_tree (use_stmt, use_expr, temp);
}
}
}
free (avdefs);
--- 2336,2420 ----
print_c_tree (dump_file, TREE_OPERAND (use_stmt, 0));
fprintf (dump_file, " on line %d\n", STMT_LINENO (use_stmt));
}
! /* Update the SSA representation for a new use of the temporary.
! Do exactly what we do for the new use generated by the save.
! */
! update_ssa_for_new_use (temp, ref_expr (use), expruse_def (use),
! ref_bb (use));
! #if DEBUGGING_SSA_UPDATE
! if (dump_file)
! {
! fprintf (dump_file, "\nUpdated a reload use:\n");
! dump_ref_list (dump_file, "", tree_refs (use_stmt), 0, 0);
! }
! #endif
! }
! }
! else if (ref_type (use) & E_PHI)
! {
! /* E_PHI's become real PHI's of the temporary. */
! tree_ref phi;
! tree_ref phiop;
! size_t i;
! splay_tree_node phidefnode;
!
! phi = create_ref (temp, V_PHI, ref_bb (use),
! BLOCK_HEAD_TREE (ref_bb (use)->index),
! NULL, NULL, false);
! add_ref_to_list_begin (bb_refs (ref_bb (use)), phi);
! splay_tree_insert (new_stmt_map,
! (splay_tree_key) use,
! (splay_tree_value) phi);
! for (i = 0; i < VARRAY_SIZE (exprphi_phi_args (use)); i++)
! {
! edge pred;
! tree_ref defby;
!
! phiop = VARRAY_GENERIC_PTR (exprphi_phi_args (use), i);
! if (!phiop || expruse_def (phiop) == NULL)
! continue;
!
! for (pred = ref_bb (use)->pred; pred; pred = pred->pred_next)
! {
! if (pred->src == ref_bb (phiop))
! break;
! }
! if (!pred)
! abort();
! defby = expruse_def (phiop);
!
! if (ref_type (expruse_def (phiop)) & E_USE)
! {
! tree_ref tempdef;
!
! phidefnode = splay_tree_lookup (new_stmt_map,
! (splay_tree_key) ref_expr (defby));
!
! if (!phidefnode)
! abort();
! tempdef = find_def_for_stmt ((tree) phidefnode->value);
!
! add_phi_arg (phi, tempdef, pred);
!
!
! if (find_list_node (reached_uses (tempdef), phi) == NULL)
! add_ref_to_list_end (reached_uses (tempdef), phi);
! if (find_list_node (imm_uses (tempdef), phi) == NULL)
! add_ref_to_list_end (imm_uses (tempdef), phi);
!
}
+ else
+ {
+ phidefnode = splay_tree_lookup (new_stmt_map,
+ (splay_tree_key) defby);
+ if (!phidefnode)
+ abort();
+ add_phi_arg (phi, (tree_ref) phidefnode->value, pred);
+
+ }
+
+ }
+
}
}
free (avdefs);
*************** tree_perform_ssapre ()
*** 2167,2172 ****
--- 2572,2579 ----
size_t j, k;

orig_expr_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
+ new_stmt_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
+
VARRAY_GENERIC_PTR_INIT (bexprs, 1, "bexprs");

/* Compute immediate dominators. */
*************** tree_perform_ssapre ()
*** 2288,2291 ****
--- 2695,2700 ----
sbitmap_vector_free (pre_dfs);
sbitmap_vector_free (domchildren);
splay_tree_delete (orig_expr_map);
+ splay_tree_delete (new_stmt_map);
+
}


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