Hello. After my param to option transformation, we lost automatic GGC detection. It's because init_ggc_heuristics is called before init_options_struct which memsets all the values to zero first.
I've tested the patch with --enable-checking=release and I hope Honza can test it more? Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin gcc/ChangeLog: 2019-11-18 Martin Liska <mli...@suse.cz> * ggc-common.c (ggc_rlimit_bound): Move to opts.c (ggc_min_expand_heuristic): Likewise. (ggc_min_heapsize_heuristic): Likewise. (init_ggc_heuristics): Likewise. * ggc.h (init_ggc_heuristics): Remove declaration. * opts.c (ggc_rlimit_bound): Moved here from ggc-common.c. (ggc_min_expand_heuristic): Likewise. (ggc_min_heapsize_heuristic): Likewise. (init_ggc_heuristics): Likewise. (init_options_struct): Init GGC params. * toplev.c (general_init): Remove call to init_ggc_heuristics. --- gcc/ggc-common.c | 103 --------------------------------------------- gcc/ggc.h | 3 -- gcc/opts.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++ gcc/toplev.c | 4 -- 4 files changed, 106 insertions(+), 110 deletions(-)
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c index f6e393d7bb6..86aab015b91 100644 --- a/gcc/ggc-common.c +++ b/gcc/ggc-common.c @@ -715,109 +715,6 @@ mmap_gt_pch_use_address (void *base, size_t size, int fd, size_t offset) } #endif /* HAVE_MMAP_FILE */ -#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT - -/* Modify the bound based on rlimits. */ -static double -ggc_rlimit_bound (double limit) -{ -#if defined(HAVE_GETRLIMIT) - struct rlimit rlim; -# if defined (RLIMIT_AS) - /* RLIMIT_AS is what POSIX says is the limit on mmap. Presumably - any OS which has RLIMIT_AS also has a working mmap that GCC will use. */ - if (getrlimit (RLIMIT_AS, &rlim) == 0 - && rlim.rlim_cur != (rlim_t) RLIM_INFINITY - && rlim.rlim_cur < limit) - limit = rlim.rlim_cur; -# elif defined (RLIMIT_DATA) - /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we - might be on an OS that has a broken mmap. (Others don't bound - mmap at all, apparently.) */ - if (getrlimit (RLIMIT_DATA, &rlim) == 0 - && rlim.rlim_cur != (rlim_t) RLIM_INFINITY - && rlim.rlim_cur < limit - /* Darwin has this horribly bogus default setting of - RLIMIT_DATA, to 6144Kb. No-one notices because RLIMIT_DATA - appears to be ignored. Ignore such silliness. If a limit - this small was actually effective for mmap, GCC wouldn't even - start up. */ - && rlim.rlim_cur >= 8 * 1024 * 1024) - limit = rlim.rlim_cur; -# endif /* RLIMIT_AS or RLIMIT_DATA */ -#endif /* HAVE_GETRLIMIT */ - - return limit; -} - -/* Heuristic to set a default for GGC_MIN_EXPAND. */ -static int -ggc_min_expand_heuristic (void) -{ - double min_expand = physmem_total (); - - /* Adjust for rlimits. */ - min_expand = ggc_rlimit_bound (min_expand); - - /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding - a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */ - min_expand /= 1024*1024*1024; - min_expand *= 70; - min_expand = MIN (min_expand, 70); - min_expand += 30; - - return min_expand; -} - -/* Heuristic to set a default for GGC_MIN_HEAPSIZE. */ -static int -ggc_min_heapsize_heuristic (void) -{ - double phys_kbytes = physmem_total (); - double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2); - - phys_kbytes /= 1024; /* Convert to Kbytes. */ - limit_kbytes /= 1024; - - /* The heuristic is RAM/8, with a lower bound of 4M and an upper - bound of 128M (when RAM >= 1GB). */ - phys_kbytes /= 8; - -#if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS) - /* Try not to overrun the RSS limit while doing garbage collection. - The RSS limit is only advisory, so no margin is subtracted. */ - { - struct rlimit rlim; - if (getrlimit (RLIMIT_RSS, &rlim) == 0 - && rlim.rlim_cur != (rlim_t) RLIM_INFINITY) - phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / 1024); - } -# endif - - /* Don't blindly run over our data limit; do GC at least when the - *next* GC would be within 20Mb of the limit or within a quarter of - the limit, whichever is larger. If GCC does hit the data limit, - compilation will fail, so this tries to be conservative. */ - limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * 1024)); - limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ()); - phys_kbytes = MIN (phys_kbytes, limit_kbytes); - - phys_kbytes = MAX (phys_kbytes, 4 * 1024); - phys_kbytes = MIN (phys_kbytes, 128 * 1024); - - return phys_kbytes; -} -#endif - -void -init_ggc_heuristics (void) -{ -#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT - param_ggc_min_expand = ggc_min_expand_heuristic (); - param_ggc_min_heapsize = ggc_min_heapsize_heuristic (); -#endif -} - /* GGC memory usage. */ class ggc_usage: public mem_usage { diff --git a/gcc/ggc.h b/gcc/ggc.h index 6c64caaafb2..04431439c5e 100644 --- a/gcc/ggc.h +++ b/gcc/ggc.h @@ -285,9 +285,6 @@ extern void ggc_print_statistics (void); extern void stringpool_statistics (void); -/* Heuristics. */ -extern void init_ggc_heuristics (void); - /* Report current heap memory use to stderr. */ extern void report_heap_memory_use (void); diff --git a/gcc/opts.c b/gcc/opts.c index addebf15365..7e363e5c1d6 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -275,6 +275,110 @@ init_opts_obstack (void) gcc_obstack_init (&opts_obstack); } +#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT + +/* Modify the bound based on rlimits. */ + +static double +ggc_rlimit_bound (double limit) +{ +#if defined(HAVE_GETRLIMIT) + struct rlimit rlim; +#if defined(RLIMIT_AS) + /* RLIMIT_AS is what POSIX says is the limit on mmap. Presumably + any OS which has RLIMIT_AS also has a working mmap that GCC will use. */ + if (getrlimit (RLIMIT_AS, &rlim) == 0 + && rlim.rlim_cur != (rlim_t) RLIM_INFINITY && rlim.rlim_cur < limit) + limit = rlim.rlim_cur; +#elif defined(RLIMIT_DATA) + /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we + might be on an OS that has a broken mmap. (Others don't bound + mmap at all, apparently.) */ + if (getrlimit (RLIMIT_DATA, &rlim) == 0 + && rlim.rlim_cur != (rlim_t) RLIM_INFINITY + && rlim.rlim_cur < limit + /* Darwin has this horribly bogus default setting of + RLIMIT_DATA, to 6144Kb. No-one notices because RLIMIT_DATA + appears to be ignored. Ignore such silliness. If a limit + this small was actually effective for mmap, GCC wouldn't even + start up. */ + && rlim.rlim_cur >= 8 * 1024 * 1024) + limit = rlim.rlim_cur; +#endif /* RLIMIT_AS or RLIMIT_DATA */ +#endif /* HAVE_GETRLIMIT */ + + return limit; +} + +/* Heuristic to set a default for GGC_MIN_EXPAND. */ + +static int +ggc_min_expand_heuristic (void) +{ + double min_expand = physmem_total (); + + /* Adjust for rlimits. */ + min_expand = ggc_rlimit_bound (min_expand); + + /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding + a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */ + min_expand /= 1024 * 1024 * 1024; + min_expand *= 70; + min_expand = MIN (min_expand, 70); + min_expand += 30; + + return min_expand; +} + +/* Heuristic to set a default for GGC_MIN_HEAPSIZE. */ +static int +ggc_min_heapsize_heuristic (void) +{ + double phys_kbytes = physmem_total (); + double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2); + + phys_kbytes /= 1024; /* Convert to Kbytes. */ + limit_kbytes /= 1024; + + /* The heuristic is RAM/8, with a lower bound of 4M and an upper + bound of 128M (when RAM >= 1GB). */ + phys_kbytes /= 8; + +#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_RSS) + /* Try not to overrun the RSS limit while doing garbage collection. + The RSS limit is only advisory, so no margin is subtracted. */ + { + struct rlimit rlim; + if (getrlimit (RLIMIT_RSS, &rlim) == 0 + && rlim.rlim_cur != (rlim_t) RLIM_INFINITY) + phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / 1024); + } +#endif + + /* Don't blindly run over our data limit; do GC at least when the + *next* GC would be within 20Mb of the limit or within a quarter of + the limit, whichever is larger. If GCC does hit the data limit, + compilation will fail, so this tries to be conservative. */ + limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * 1024)); + limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ()); + phys_kbytes = MIN (phys_kbytes, limit_kbytes); + + phys_kbytes = MAX (phys_kbytes, 4 * 1024); + phys_kbytes = MIN (phys_kbytes, 128 * 1024); + + return phys_kbytes; +} +#endif + +static void +init_ggc_heuristics (void) +{ +#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT + param_ggc_min_expand = ggc_min_expand_heuristic (); + param_ggc_min_heapsize = ggc_min_heapsize_heuristic (); +#endif +} + /* Initialize OPTS and OPTS_SET before using them in parsing options. */ void @@ -289,6 +393,8 @@ init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set) if (opts_set) memset (opts_set, 0, sizeof (*opts_set)); + init_ggc_heuristics (); + /* Initialize whether `char' is signed. */ opts->x_flag_signed_char = DEFAULT_SIGNED_CHAR; /* Set this to a special "uninitialized" value. The actual default diff --git a/gcc/toplev.c b/gcc/toplev.c index d4583bac66c..fa6d39355d0 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1240,10 +1240,6 @@ general_init (const char *argv0, bool init_signals) /* Initialize register usage now so switches may override. */ init_reg_sets (); - /* This must be done after global_init_params but before argument - processing. */ - init_ggc_heuristics (); - /* Create the singleton holder for global state. This creates the dump manager. */ g = new gcc::context ();