public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/4] True IPA reimplementation of IPA-SRA (v4)
@ 2019-08-21 17:32 Martin Jambor
  2019-08-21 17:44 ` [PATCH 4/4] Modifications to the testsuite Martin Jambor
                   ` (4 more replies)
  0 siblings, 5 replies; 21+ messages in thread
From: Martin Jambor @ 2019-08-21 17:32 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jan Hubicka, Jan Hubicka

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 9995 bytes --]

Hello,

I have fixed two bugs of the previous IPA-SRA submission and re-based
it on a recent trunk and am posting it again so that people can have
look at an up-to-date version (and also as a reminder that it is still
pending review).  Previous submissions are available at:

   - https://gcc.gnu.org/ml/gcc-patches/2019-07/msg01529.html and
   - https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00472.html

This reimplementation is a full IPA pass that can handle strictly
connected components in the call-graph, can take advantage of LTO and
does not weirdly switch functions in pass-pipeline like our current
quasi-IPA SRA does.  Unlike the current IPA-SRA it can also remove
return values, even in SCCs.  On the other hand, it is less powerful
when it comes to structures passed by reference.  By design it will
not create references to bits of an aggregate because that turned out
to be just obfuscation in practice.  However, it also cannot usually
split aggregates passed by reference that are just passed to another
function (where splitting would be useful) because it cannot perform
the same TBAA analysis like the current implementation which already
knows what types it should look at because it has access to bodies of
all functions attempts to modify (for an example see
https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00955.html).

Since May I have switched the order of IPA-CP and IPA-SRA, so that
IPA-CP is run before IPA-SRA and it can propagate constants in
aggregates before these are split and tracking is lost.  The July
submission frequently cloned even if all the parameter removal work
has already been done by IPA-CP, this version does not have that
problem.  Like before, there are dbgcounters.

This submission has
https://gcc.gnu.org/ml/gcc-patches/2019-07/msg01567.html incorporated.

The patch has successfully bootstrapped and LTO-profilebootstrapped
and tested on x86_64-linux.  Testing on x86_64 fixes 24 LTO tests in
guality/pr68860-1.c but regresses 13 guality tests, 3 of which are not
LTO.  I plan to bootstrap on ppc64le and aarch64 like I did before
submitting the previous version.  Right after my last submission,
Martin Liška used a version which contained both aforementioned fixes
(but of course not the re-base) to build over 5000 openSUSE packages
(vast majority of them with LTO).

After the patches are approved, I would like to commit them in one big
commit but in order to ease review, I have split the big patch into
four patches:
  1. Removal of old IPA-SRA,
  2. New parameter manipulation infrastructure,
  3. New IPA-SRA implementation, and
  4. Modifications to the testsuite.

When applied one after another they should compile but I have only
exhaustively tested the complete patch.  If you want to experiment
with new IPA-SRA or the parameter manipulation infrastructure it
introduces, I suggest that you clone the jamborm/ipa-sra branch from
our git "mirror"
(https://gcc.gnu.org/git/?p=gcc.git;a=shortlog;h=refs/heads/jamborm/ipa-sra).

Thanks in advance for any questions, comments and suggestions,

Martin


2019-08-20  Martin Jambor  <mjambor@suse.cz>

        * coretypes.h (cgraph_edge): Declare.
        * ipa-param-manipulation.c: Rewrite.
        * ipa-param-manipulation.h: Likewise.
        * Makefile.in (GTFILES): Added ipa-param-manipulation.h and ipa-sra.c.
        (OBJS): Added ipa-sra.o.
        * cgraph.h (ipa_replace_map): Removed fields old_tree, replace_p
        and ref_p, added fields param_adjustments and performed_splits.
        (struct cgraph_clone_info): Remove ags_to_skip and
        combined_args_to_skip, new field param_adjustments.
        (cgraph_node::create_clone): Changed parameters to use
        ipa_param_adjustments.
        (cgraph_node::create_virtual_clone): Likewise.
        (cgraph_node::create_virtual_clone_with_body): Likewise.
        (tree_function_versioning): Likewise.
        (cgraph_build_function_type_skip_args): Removed.
        * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Convert to
        using ipa_param_adjustments.
        (clone_of_p): Likewise.
        * cgraphclones.c (cgraph_build_function_type_skip_args): Removed.
        (build_function_decl_skip_args): Likewise.
        (duplicate_thunk_for_node): Adjust parameters using
        ipa_param_body_adjustments, copy param_adjustments instead of
        args_to_skip.
        (cgraph_node::create_clone): Convert to using ipa_param_adjustments.
        (cgraph_node::create_virtual_clone): Likewise.
        (cgraph_node::create_version_clone_with_body): Likewise.
        (cgraph_materialize_clone): Likewise.
        (symbol_table::materialize_all_clones): Likewise.
        * ipa-fnsummary.c (ipa_fn_summary_t::duplicate): Simplify
        ipa_replace_map check.
        * ipa-cp.c (get_replacement_map): Do not initialize removed fields.
        (initialize_node_lattices): Make aware that some parameters might have
        already been removed.
        (want_remove_some_param_p): New function.
        (create_specialized_node): Convert to using ipa_param_adjustments and
        deal with possibly pre-existing adjustments.
        * lto-cgraph.c (output_cgraph_opt_summary_p): Likewise.
        (output_node_opt_summary): Do not stream removed fields.  Stream
        parameter adjustments instead of argumetns to skip.
        (input_node_opt_summary): Likewise.
        (input_node_opt_summary): Likewise.
        * lto-section-in.c (lto_section_name): Added ipa-sra section.
        * lto-streamer.h (lto_section_type): Likewise.
        * tree-inline.h (copy_body_data): New fields killed_new_ssa_names and
	param_body_adjs.
        (copy_decl_to_var): Declare.
        * tree-inline.c (update_clone_info): Do not remap old_tree.
        (remap_gimple_stmt): Use ipa_param_body_adjustments to modify gimple
        statements, walk all extra generated statements and remap their
        operands.
        (redirect_all_calls): Add killed SSA names to a hash set.
        (remap_ssa_name): Do not remap killed SSA names.
        (copy_arguments_for_versioning): Renames to copy_arguments_nochange,
        half of functionality moved to ipa_param_body_adjustments.
        (copy_decl_to_var): Make exported.
        (copy_body): Destroy killed_new_ssa_names hash set.
        (expand_call_inline): Remap performed splits.
        (update_clone_info): Likewise.
        (tree_function_versioning): Simplify tree_map processing.  Updated to
        accept ipa_param_adjustments and use ipa_param_body_adjustments.
        * omp-simd-clone.c (simd_clone_vector_of_formal_parm_types): Adjust
        for the new interface.
        (simd_clone_clauses_extract): Likewise, make args an auto_vec.
        (simd_clone_compute_base_data_type): Likewise.
        (simd_clone_init_simd_arrays): Adjust for the new interface.
        (simd_clone_adjust_argument_types): Likewise.
        (struct modify_stmt_info): Likewise.
        (ipa_simd_modify_stmt_ops): Likewise.
        (ipa_simd_modify_function_body): Likewise.
        (simd_clone_adjust): Likewise.
        * tree-sra.c: Removed IPA-SRA.  Include tree-sra.h.
        (type_internals_preclude_sra_p): Make public.
        * tree-sra.h: New file.
        * ipa-inline-transform.c (save_inline_function_body): Update to
        refelct new tree_function_versioning signature.
        * ipa-prop.c (adjust_agg_replacement_values): Use a helper from
        ipa_param_adjustments to get current parameter indices.
        (ipcp_modif_dom_walker::before_dom_children): Likewise.
        (ipcp_update_bits): Likewise.
        (ipcp_update_vr): Likewise.
        * ipa-split.c (split_function): Convert to using ipa_param_adjustments.
        * ipa-sra.c: New file.
        * multiple_target.c (create_target_clone): Update to reflet new type
        of create_version_clone_with_body.
        * trans-mem.c (ipa_tm_create_version): Update to reflect new type of
        tree_function_versioning.
	(modify_function): Update to reflect new type of
	tree_function_versioning.
        * params.def (PARAM_IPA_SRA_MAX_REPLACEMENTS): New.
        * passes.def: Remove old IPA-SRA and add new one.
        * tree-pass.h (make_pass_early_ipa_sra): Remove declaration.
        (make_pass_ipa_sra): Declare.
	* dbgcnt.def: Remove eipa_sra.  Added ipa_sra_params and
	ipa_sra_retvalues.
	* doc/invoke.texi (ipa-sra-max-replacements): New.

        testsuite/
        * g++.dg/ipa/pr81248.C: Adjust dg-options and dump-scan.
        * gcc.dg/ipa/ipa-sra-1.c: Likewise.
        * gcc.dg/ipa/ipa-sra-10.c: Likewise.
        * gcc.dg/ipa/ipa-sra-11.c: Likewise.
        * gcc.dg/ipa/ipa-sra-3.c: Likewise.
        * gcc.dg/ipa/ipa-sra-4.c: Likewise.
        * gcc.dg/ipa/ipa-sra-5.c: Likewise.
        * gcc.dg/ipa/ipacost-2.c: Disable ipa-sra.
        * gcc.dg/ipa/ipcp-agg-9.c: Likewise.
        * gcc.dg/ipa/pr78121.c: Adjust scan pattern.
        * gcc.dg/ipa/vrp1.c: Likewise.
        * gcc.dg/ipa/vrp2.c: Likewise.
        * gcc.dg/ipa/vrp3.c: Likewise.
        * gcc.dg/ipa/vrp7.c: Likewise.
        * gcc.dg/ipa/vrp8.c: Likewise.
        * gcc.dg/noreorder.c: use noipa attribute instead of noinline.
        * gcc.dg/ipa/20040703-wpa.c: New test.
	* gcc.dg/ipa/ipa-sra-12.c: New test.
	* gcc.dg/ipa/ipa-sra-13.c: Likewise.
	* gcc.dg/ipa/ipa-sra-14.c: Likewise.
	* gcc.dg/ipa/ipa-sra-15.c: Likewise.
	* gcc.dg/ipa/ipa-sra-16.c: Likewise.
	* gcc.dg/ipa/ipa-sra-17.c: Likewise.
	* gcc.dg/ipa/ipa-sra-18.c: Likewise.
	* gcc.dg/ipa/ipa-sra-19.c: Likewise.
	* gcc.dg/ipa/ipa-sra-20.c: Likewise.
	* gcc.dg/ipa/ipa-sra-21.c: Likewise.
	* gcc.dg/ipa/ipa-sra-22.c: Likewise.
	* gcc.dg/sso/ipa-sra-1.c: Likewise.
	* g++.dg/ipa/ipa-sra-2.C: Likewise.
	* g++.dg/ipa/ipa-sra-3.C: Likewise.
	* gcc.dg/tree-ssa/ipa-cp-1.c: Make return value used.
	* g++.dg/ipa/devirt-19.C: Add missing return, add -fipa-cp-clone
	option.
	* g++.dg/lto/devirt-19_0.C: Add -fipa-cp-clone option.

	* gcc.dg/ipa/ipa-sra-2.c: Mark to be removed.
	* gcc.dg/ipa/ipa-sra-6.c: Likewise.

^ permalink raw reply	[flat|nested] 21+ messages in thread
* [PATCH 0/4] True IPA reimplementation of IPA-SRA (v3)
@ 2019-07-23 17:08 Martin Jambor
  2019-07-23 17:08 ` [PATCH 4/4] Modifications to the testsuite Martin Jambor
  0 siblings, 1 reply; 21+ messages in thread
From: Martin Jambor @ 2019-07-23 17:08 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jan Hubicka

Hello,

I have been working a bit more on the IPA-SRA reimplementation that I
have previously posted here in:

   https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00472.html


This reimplementation is a full IPA pass that can handle strictly
connected components in the call-graph, can take advantage of LTO and
does not weirdly switch functions in pass-pipeline like our current
quasi-IPA SRA does.  Unlike the current IPA-SRA it can also remove
return values, even in SCCs.  On the other hand, it is less powerful
when it comes to structures passed by reference.  By design it will
not create references to bits of an aggregate because that turned out
to be just obfuscation in practice.  However, it also cannot usually
split aggregates passed by reference that are just passed to another
function (where splitting would be useful) because it cannot perform
the same TBAA analysis like the current implementation which already
knows what types it should look at because it has access to bodies of
all functions attempts to modify (for an example see
https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00955.html).

Since May I have switched the order of IPA-CP and IPA-SRA, so that
IPA-CP is run before IPA-SRA and it can propagate constants in
aggregates before these are split and tracking is lost.  This has
uncovered two small bugs, as did LTO-building Mozilla Firefox with the
patch and another issue was discovered when bootstrapping on ppc64le.
All of these are fixed.  I have also added two dbgcounters, one for
processing parameters and another for return values removal.

The patch has successfully bootstrapped, LTO-bootstrapped and
LTO-profilebootstrapped on x86_64-linux.  Testing on x86_64 fixes 24
LTO tests in guality/pr68860-1.c but regresses 13 guality tests, 3 of
which are not LTO.  Ther patch also passed bootstrap and testing on
aarch64-linux and ppc64le-linux.

When building the big libxul library of Mozilla Firefox with both LTO
and profile feedback, the patch has modified 21093 functions out of
259745 it has seen, so slightly over 8%.  In the process, it has
removed 6693 unused return values and 1538 unused parameters and split
7126 parameters into 8394 smaller components.  Note that IPA-CP can
also remove unused scalar parameters in simple situations, and since
it now runs first, the 1538 are only those which IPA-CP left behind
for one reason or another.  The built Firefux could browse the Amazon
web site for a while without any apparent problem.

After the patches are approved, I would like to commit them in one big
commit but in order to ease review I have split the big patch into
four smaller (but still rather big) ones:
  1. Removal of old IPA-SRA,
  2. New parameter manipulation infrastructure,
  3. New IPA-SRA implementation, and
  4. Modifications to the testsuite.

When applied one after another they should compile but I have only
exhaustively tested the complete patch.  If you want to experiment
with new IPA-SRA or the parameter manipulation infrastructure it
introduces, I suggest that you clone the jamborm/ipa-sra branch from
our git "mirror"
(https://gcc.gnu.org/git/?p=gcc.git;a=shortlog;h=refs/heads/jamborm/ipa-sra).

Thanks in advance for any questions, comments and suggestions,

Martin



2019-07-23  Martin Jambor  <mjambor@suse.cz>

        * coretypes.h (cgraph_edge): Declare.
        * ipa-param-manipulation.c: Rewrite.
        * ipa-param-manipulation.h: Likewise.
        * Makefile.in (GTFILES): Added ipa-param-manipulation.h and ipa-sra.c.
        (OBJS): Added ipa-sra.o.
        * cgraph.h (ipa_replace_map): Removed fields old_tree, replace_p
        and ref_p, added fields param_adjustments and performed_splits.
        (struct cgraph_clone_info): Remove ags_to_skip and
        combined_args_to_skip, new field param_adjustments.
        (cgraph_node::create_clone): Changed parameters to use
        ipa_param_adjustments.
        (cgraph_node::create_virtual_clone): Likewise.
        (cgraph_node::create_virtual_clone_with_body): Likewise.
        (tree_function_versioning): Likewise.
        (cgraph_build_function_type_skip_args): Removed.
        * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Convert to
        using ipa_param_adjustments.
        (clone_of_p): Likewise.
        * cgraphclones.c (cgraph_build_function_type_skip_args): Removed.
        (build_function_decl_skip_args): Likewise.
        (duplicate_thunk_for_node): Adjust parameters using
        ipa_param_body_adjustments, copy param_adjustments instead of
        args_to_skip.
        (cgraph_node::create_clone): Convert to using ipa_param_adjustments.
        (cgraph_node::create_virtual_clone): Likewise.
        (cgraph_node::create_version_clone_with_body): Likewise.
        (cgraph_materialize_clone): Likewise.
        (symbol_table::materialize_all_clones): Likewise.
        * ipa-fnsummary.c (ipa_fn_summary_t::duplicate): Simplify
        ipa_replace_map check.
        * ipa-cp.c (get_replacement_map): Do not initialize removed fields.
        (initialize_node_lattices): Make aware that some parameters might have
        already been removed.
        (want_remove_some_param_p): New function.
        (create_specialized_node): Convert to using ipa_param_adjustments and
        deal with possibly pre-existing adjustments.
        * lto-cgraph.c (output_cgraph_opt_summary_p): Likewise.
        (output_node_opt_summary): Do not stream removed fields.  Stream
        parameter adjustments instead of argumetns to skip.
        (input_node_opt_summary): Likewise.
        (input_node_opt_summary): Likewise.
        * lto-section-in.c (lto_section_name): Added ipa-sra section.
        * lto-streamer.h (lto_section_type): Likewise.
        * tree-inline.h (copy_body_data): New fields killed_new_ssa_names and
	param_body_adjs.
        (copy_decl_to_var): Declare.
        * tree-inline.c (update_clone_info): Do not remap old_tree.
        (remap_gimple_stmt): Use ipa_param_body_adjustments to modify gimple
        statements, walk all extra generated statements and remap their
        operands.
        (redirect_all_calls): Add killed SSA names to a hash set.
        (remap_ssa_name): Do not remap killed SSA names.
        (copy_arguments_for_versioning): Renames to copy_arguments_nochange,
        half of functionality moved to ipa_param_body_adjustments.
        (copy_decl_to_var): Make exported.
        (copy_body): Destroy killed_new_ssa_names hash set.
        (expand_call_inline): Remap performed splits.
        (update_clone_info): Likewise.
        (tree_function_versioning): Simplify tree_map processing.  Updated to
        accept ipa_param_adjustments and use ipa_param_body_adjustments.
        * omp-simd-clone.c (simd_clone_vector_of_formal_parm_types): Adjust
        for the new interface.
        (simd_clone_clauses_extract): Likewise, make args an auto_vec.
        (simd_clone_compute_base_data_type): Likewise.
        (simd_clone_init_simd_arrays): Adjust for the new interface.
        (simd_clone_adjust_argument_types): Likewise.
        (struct modify_stmt_info): Likewise.
        (ipa_simd_modify_stmt_ops): Likewise.
        (ipa_simd_modify_function_body): Likewise.
        (simd_clone_adjust): Likewise.
        * tree-sra.c: Removed IPA-SRA.  Include tree-sra.h.
        (type_internals_preclude_sra_p): Make public.
        * tree-sra.h: New file.
        * ipa-inline-transform.c (save_inline_function_body): Update to
        refelct new tree_function_versioning signature.
        * ipa-prop.c (adjust_agg_replacement_values): Use a helper from
        ipa_param_adjustments to get current parameter indices.
        (ipcp_modif_dom_walker::before_dom_children): Likewise.
        (ipcp_update_bits): Likewise.
        (ipcp_update_vr): Likewise.
        * ipa-split.c (split_function): Convert to using ipa_param_adjustments.
        * ipa-sra.c: New file.
        * multiple_target.c (create_target_clone): Update to reflet new type
        of create_version_clone_with_body.
        * trans-mem.c (ipa_tm_create_version): Update to reflect new type of
        tree_function_versioning.
	(modify_function): Update to reflect new type of
	tree_function_versioning.
        * params.def (PARAM_IPA_SRA_MAX_REPLACEMENTS): New.
        * passes.def: Remove old IPA-SRA and add new one.
        * tree-pass.h (make_pass_early_ipa_sra): Remove declaration.
        (make_pass_ipa_sra): Declare.
	* dbgcnt.def: Remove eipa_sra.  Added ipa_sra_params and
	ipa_sra_retvalues.
	* doc/invoke.texi (ipa-sra-max-replacements): New.

        testsuite/
        * g++.dg/ipa/pr81248.C: Adjust dg-options and dump-scan.
        * gcc.dg/ipa/ipa-sra-1.c: Likewise.
        * gcc.dg/ipa/ipa-sra-10.c: Likewise.
        * gcc.dg/ipa/ipa-sra-11.c: Likewise.
        * gcc.dg/ipa/ipa-sra-3.c: Likewise.
        * gcc.dg/ipa/ipa-sra-4.c: Likewise.
        * gcc.dg/ipa/ipa-sra-5.c: Likewise.
        * gcc.dg/ipa/ipacost-2.c: Disable ipa-sra.
        * gcc.dg/ipa/ipcp-agg-9.c: Likewise.
        * gcc.dg/ipa/pr78121.c: Adjust scan pattern.
        * gcc.dg/ipa/vrp1.c: Likewise.
        * gcc.dg/ipa/vrp2.c: Likewise.
        * gcc.dg/ipa/vrp3.c: Likewise.
        * gcc.dg/ipa/vrp7.c: Likewise.
        * gcc.dg/ipa/vrp8.c: Likewise.
        * gcc.dg/noreorder.c: use noipa attribute instead of noinline.
        * gcc.dg/ipa/20040703-wpa.c: New test.
	* gcc.dg/ipa/ipa-sra-12.c: New test.
	* gcc.dg/ipa/ipa-sra-13.c: Likewise.
	* gcc.dg/ipa/ipa-sra-14.c: Likewise.
	* gcc.dg/ipa/ipa-sra-15.c: Likewise.
	* gcc.dg/ipa/ipa-sra-16.c: Likewise.
	* gcc.dg/ipa/ipa-sra-17.c: Likewise.
	* gcc.dg/ipa/ipa-sra-18.c: Likewise.
	* gcc.dg/ipa/ipa-sra-19.c: Likewise.
	* gcc.dg/ipa/ipa-sra-20.c: Likewise.
	* gcc.dg/ipa/ipa-sra-21.c: Likewise.
	* gcc.dg/ipa/ipa-sra-22.c: Likewise.
	* gcc.dg/sso/ipa-sra-1.c: Likewise.
	* g++.dg/ipa/ipa-sra-2.C: Likewise.
	* g++.dg/ipa/ipa-sra-3.C: Likewise.
	* gcc.dg/tree-ssa/ipa-cp-1.c: Make return value used.
	* g++.dg/ipa/devirt-19.C: Add missing return, add -fipa-cp-clone
	option.
	* g++.dg/lto/devirt-19_0.C: Add -fipa-cp-clone option.

	* gcc.dg/ipa/ipa-sra-2.c: Mark to be removed.
	* gcc.dg/ipa/ipa-sra-6.c: Likewise.

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2019-10-03 12:18 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-21 17:32 [PATCH 0/4] True IPA reimplementation of IPA-SRA (v4) Martin Jambor
2019-08-21 17:44 ` [PATCH 4/4] Modifications to the testsuite Martin Jambor
2019-09-13 18:01   ` Jan Hubicka
2019-10-02 19:29   ` Andreas Schwab
2019-10-02 21:15     ` Segher Boessenkool
2019-10-03 12:18     ` Martin Jambor
2019-08-21 18:09 ` [PATCH 2/4] New parameter manipulation infrastructure Martin Jambor
2019-09-13 17:40   ` Jan Hubicka
2019-09-19  9:55     ` Martin Jambor
2019-08-21 18:24 ` [PATCH 3/4] New IPA-SRA implementation Martin Jambor
2019-09-13 18:00   ` Jan Hubicka
2019-09-19 16:21     ` Martin Jambor
2019-09-21 14:26   ` Richard Sandiford
2019-09-24 17:43     ` Martin Jambor
2019-09-25 14:18       ` [PATCH] Fix continue condition in IPA-SRA's process_scan_results Martin Jambor
2019-09-26  7:33         ` Richard Biener
2019-08-21 18:36 ` [PATCH 1/4] Remove old IPA-SRA, introduce tree-sra.h Martin Jambor
2019-09-13 17:29   ` Jan Hubicka
2019-09-19 22:30 ` [PATCH 0/4] True IPA reimplementation of IPA-SRA (v4) Martin Jambor
  -- strict thread matches above, loose matches on Subject: below --
2019-07-23 17:08 [PATCH 0/4] True IPA reimplementation of IPA-SRA (v3) Martin Jambor
2019-07-23 17:08 ` [PATCH 4/4] Modifications to the testsuite Martin Jambor
2019-08-09 21:50   ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).