[gcc r15-7323] options: Adjust cl_optimization_compare to avoid checking ICE [PR115913]
https://gcc.gnu.org/g:c0008df2118233f1afbed76ce308b4dfb6e6fc1a commit r15-7323-gc0008df2118233f1afbed76ce308b4dfb6e6fc1a Author: Lewis Hyatt Date: Sun Jan 26 18:57:00 2025 -0500 options: Adjust cl_optimization_compare to avoid checking ICE [PR115913] At the end of a sequence like: #pragma GCC push_options ... #pragma GCC pop_options the handler for pop_options calls cl_optimization_compare() (as generated by optc-save-gen.awk) to make sure that all global state has been restored to the value it had prior to the push_options call. The verification is performed for almost all entries in the global_options struct. This leads to unexpected checking asserts, as discussed in the PR, in case the state of warnings-related options has been intentionally modified in between push_options and pop_options via a call to #pragma GCC diagnostic. Address that by skipping the verification for CL_WARNING-flagged options. gcc/ChangeLog: PR middle-end/115913 * optc-save-gen.awk (cl_optimization_compare): Skip options with CL_WARNING flag. gcc/testsuite/ChangeLog: PR middle-end/115913 * c-c++-common/cpp/pr115913.c: New test. Diff: --- gcc/optc-save-gen.awk | 5 + gcc/testsuite/c-c++-common/cpp/pr115913.c | 7 +++ 2 files changed, 12 insertions(+) diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk index fa9218472edc..a3d7e5a478e4 100644 --- a/gcc/optc-save-gen.awk +++ b/gcc/optc-save-gen.awk @@ -1484,6 +1484,11 @@ for (i = 0; i < n_opts; i++) { if (name == "") continue; + # We do not want to compare warning-related options, since they + # might have been modified by a #pragma GCC diagnostic. + if (flag_set_p("Warning", flags[i])) + continue; + if (name in checked_options) continue; checked_options[name]++ diff --git a/gcc/testsuite/c-c++-common/cpp/pr115913.c b/gcc/testsuite/c-c++-common/cpp/pr115913.c new file mode 100644 index ..b9d10cda8d24 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/pr115913.c @@ -0,0 +1,7 @@ +/* { dg-do preprocess } */ +/* PR middle-end/115913 */ +#pragma GCC push_options +#pragma GCC diagnostic warning "-Wundef" +/* The call to cl_optimization_compare performed by pop_options should not + lead to a checking failure. */ +#pragma GCC pop_options
[gcc r15-7324] PR modula2/117411 Request for documentation to include exception example
https://gcc.gnu.org/g:969c30885558d092ad07c9c71dd54ea14f6096c6 commit r15-7324-g969c30885558d092ad07c9c71dd54ea14f6096c6 Author: Gaius Mulley Date: Sun Feb 2 16:02:27 2025 + PR modula2/117411 Request for documentation to include exception example This patch adds a new section to the gm2 documentation and new corresponding testcode to the regression testsuite. gcc/ChangeLog: PR modula2/117411 * doc/gm2.texi (Exception handling): New section. (The ISO system module): Add description of COFF_T. (Assembler language): Tidy up last sentance. gcc/testsuite/ChangeLog: PR modula2/117411 * gm2/iso/run/pass/except9.mod: New test. * gm2/iso/run/pass/lazyunique.mod: New test. Signed-off-by: Gaius Mulley Diff: --- gcc/doc/gm2.texi | 162 -- gcc/testsuite/gm2/iso/run/pass/except9.mod| 78 + gcc/testsuite/gm2/iso/run/pass/lazyunique.mod | 87 ++ 3 files changed, 318 insertions(+), 9 deletions(-) diff --git a/gcc/doc/gm2.texi b/gcc/doc/gm2.texi index f8ae148b99ba..8baee24f14e0 100644 --- a/gcc/doc/gm2.texi +++ b/gcc/doc/gm2.texi @@ -234,6 +234,7 @@ such as the AVR and the ARM). * Extensions::GNU Modula-2 language extensions. * Type compatibility::Data type compatibility. * Unbounded by reference::Explanation of a language optimization. +* Exception handling::Example of exception handling. * Building a shared library:: How to build a shared library. * Interface for Python:: How to produce swig interface files. * Producing a Python module:: How to produce a Python module. @@ -1837,7 +1838,7 @@ are all exported from the @code{SYSTEM} module. @xref{The PIM system module}. @xref{The ISO system module}. -@node Type compatibility, Unbounded by reference, Extensions, Using +@node Type compatibility, Exception handling, Extensions, Using @section Type compatibility This section discuss the issues surrounding assignment, expression @@ -1985,7 +1986,148 @@ The types @code{BYTE}, @code{LOC}, @code{WORD} and @code{WORD}n derivatives are assignment and parameter compatible with any data type of the same size. -@node Unbounded by reference, Building a shared library, Type compatibility, Using +@node Exception handling, Unbounded by reference, Type compatibility, Using +@section Exception handling + +This section gives an example of exception handling and briefly +describes its runtime behavior. The module below is written in the +ISO dialect of Modula-2 and can be compiled with the command line: + +@example +$ gm2 -g -fiso -fsoft-check-all lazyunique.mod +@end example + +The option @samp{-fsoft-check-all} generates checks for @code{NIL} +pointer access violation. In turn this will call the exception handler. + +@example +@group +MODULE lazyunique ; (*!m2iso+gm2*) + +FROM Storage IMPORT ALLOCATE ; +FROM libc IMPORT printf, exit ; + +TYPE + List = POINTER TO RECORD +next : List ; +value: INTEGER ; + END ; + + Array = ARRAY [0..3] OF INTEGER ; + +CONST + Unsorted = Array @{0, 2, 1, 1@} ; + +VAR + head: List ; +@end group +@end example + +@example +@group +PROCEDURE Display ; +VAR + p: List ; +BEGIN + p := head^.next ; + printf ("\nunique data\n"); + printf ("===\n"); + WHILE p # NIL DO + printf ("%d\n", p^.value); + p := p^.next + END +END Display ; +@end group +@end example + +@example +@group +PROCEDURE Add (VAR p: List; val: INTEGER) ; +BEGIN + NEW (p) ; + WITH p^ DO + value := val ; + next := NIL + END +END Add ; +@end group +@end example + +@example +@group +PROCEDURE Unique (val: INTEGER) ; +VAR + p: List ; +BEGIN + printf ("new value %d\n", val); + p := head ; + (* The following line may cause an exception accessing next or + value. *) + WHILE p^.next^.value # val DO + p := p^.next + END +EXCEPT + (* Now fixup. Determine the source of the exception and retry. *) + IF head = NIL + THEN + printf ("list was empty, add sentinal\n"); + Add (head, -1) ; + RETRY (* Jump back to the begin statement. *) + ELSIF p^.next = NIL + THEN + printf ("growing the list\n"); + Add (p^.next, val) ; + RETRY (* Jump back to the begin statement. *) + ELSE + printf ("should never reach here!\n"); + END +END Unique ; +@end group +@end example + +@example +@group +PROCEDURE unique ; +VAR + i: CARDINAL ; +BEGIN + FOR i := 0 TO HIGH (Unsorted) DO + Unique (Unsorted[i]) + END ; + Display +END unique ; + +BEGIN + head := NIL ; + unique +END lazyunique. +@end group +@end example + +@example +@group +new value 0 +list was empty, add sentinal +new value 0 +growing the list +new value 0 +new value 2 +growing the list +new value 2 +new value 1 +growing the
[gcc r14-11269] options: Adjust cl_optimization_compare to avoid checking ICE [PR115913]
https://gcc.gnu.org/g:1e77549e1860249abafb8fc325fc4c1885b0d8c4 commit r14-11269-g1e77549e1860249abafb8fc325fc4c1885b0d8c4 Author: Lewis Hyatt Date: Sun Jan 26 18:57:00 2025 -0500 options: Adjust cl_optimization_compare to avoid checking ICE [PR115913] At the end of a sequence like: #pragma GCC push_options ... #pragma GCC pop_options the handler for pop_options calls cl_optimization_compare() (as generated by optc-save-gen.awk) to make sure that all global state has been restored to the value it had prior to the push_options call. The verification is performed for almost all entries in the global_options struct. This leads to unexpected checking asserts, as discussed in the PR, in case the state of warnings-related options has been intentionally modified in between push_options and pop_options via a call to #pragma GCC diagnostic. Address that by skipping the verification for CL_WARNING-flagged options. gcc/ChangeLog: PR middle-end/115913 * optc-save-gen.awk (cl_optimization_compare): Skip options with CL_WARNING flag. gcc/testsuite/ChangeLog: PR middle-end/115913 * c-c++-common/cpp/pr115913.c: New test. Diff: --- gcc/optc-save-gen.awk | 5 + gcc/testsuite/c-c++-common/cpp/pr115913.c | 7 +++ 2 files changed, 12 insertions(+) diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk index a3af88e37760..2d36e58677b6 100644 --- a/gcc/optc-save-gen.awk +++ b/gcc/optc-save-gen.awk @@ -1467,6 +1467,11 @@ for (i = 0; i < n_opts; i++) { if (name == "") continue; + # We do not want to compare warning-related options, since they + # might have been modified by a #pragma GCC diagnostic. + if (flag_set_p("Warning", flags[i])) + continue; + if (name in checked_options) continue; checked_options[name]++ diff --git a/gcc/testsuite/c-c++-common/cpp/pr115913.c b/gcc/testsuite/c-c++-common/cpp/pr115913.c new file mode 100644 index ..b9d10cda8d24 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/pr115913.c @@ -0,0 +1,7 @@ +/* { dg-do preprocess } */ +/* PR middle-end/115913 */ +#pragma GCC push_options +#pragma GCC diagnostic warning "-Wundef" +/* The call to cl_optimization_compare performed by pop_options should not + lead to a checking failure. */ +#pragma GCC pop_options
[gcc r13-9361] options: Adjust cl_optimization_compare to avoid checking ICE [PR115913]
https://gcc.gnu.org/g:e097b376f170d531b86e6e6dc763db0ab5a8700d commit r13-9361-ge097b376f170d531b86e6e6dc763db0ab5a8700d Author: Lewis Hyatt Date: Sun Jan 26 18:57:00 2025 -0500 options: Adjust cl_optimization_compare to avoid checking ICE [PR115913] At the end of a sequence like: #pragma GCC push_options ... #pragma GCC pop_options the handler for pop_options calls cl_optimization_compare() (as generated by optc-save-gen.awk) to make sure that all global state has been restored to the value it had prior to the push_options call. The verification is performed for almost all entries in the global_options struct. This leads to unexpected checking asserts, as discussed in the PR, in case the state of warnings-related options has been intentionally modified in between push_options and pop_options via a call to #pragma GCC diagnostic. Address that by skipping the verification for CL_WARNING-flagged options. gcc/ChangeLog: PR middle-end/115913 * optc-save-gen.awk (cl_optimization_compare): Skip options with CL_WARNING flag. gcc/testsuite/ChangeLog: PR middle-end/115913 * c-c++-common/cpp/pr115913.c: New test. Diff: --- gcc/optc-save-gen.awk | 5 + gcc/testsuite/c-c++-common/cpp/pr115913.c | 7 +++ 2 files changed, 12 insertions(+) diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk index d2cb53c477fd..05bb408d 100644 --- a/gcc/optc-save-gen.awk +++ b/gcc/optc-save-gen.awk @@ -1467,6 +1467,11 @@ for (i = 0; i < n_opts; i++) { if (name == "") continue; + # We do not want to compare warning-related options, since they + # might have been modified by a #pragma GCC diagnostic. + if (flag_set_p("Warning", flags[i])) + continue; + if (name in checked_options) continue; checked_options[name]++ diff --git a/gcc/testsuite/c-c++-common/cpp/pr115913.c b/gcc/testsuite/c-c++-common/cpp/pr115913.c new file mode 100644 index ..b9d10cda8d24 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/pr115913.c @@ -0,0 +1,7 @@ +/* { dg-do preprocess } */ +/* PR middle-end/115913 */ +#pragma GCC push_options +#pragma GCC diagnostic warning "-Wundef" +/* The call to cl_optimization_compare performed by pop_options should not + lead to a checking failure. */ +#pragma GCC pop_options
[gcc r15-7326] Add tunables for input buffer
https://gcc.gnu.org/g:ae814afad900edf1f19850985614398e0875618c commit r15-7326-gae814afad900edf1f19850985614398e0875618c Author: Andi Kleen Date: Wed Dec 25 11:54:13 2024 -0800 Add tunables for input buffer The input machinery to read the source code independent of the lexer has a range of hard coded maximum array sizes that can impact performance. Make them tunable. input.cc is part of libcommon so it cannot direct access params without a level of indirection. gcc/ChangeLog: PR preprocessor/118168 * input.cc (file_cache::tune): New function. * input.h (class file_cache): Make tunables non const. * params.opt: Add new tunables. * toplev.cc (toplev::main): Initialize input buffer context tunables. Diff: --- gcc/input.cc | 18 +- gcc/input.h| 4 +++- gcc/params.opt | 8 gcc/toplev.cc | 2 ++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/gcc/input.cc b/gcc/input.cc index 9f3cc6651e83..8605202fed2c 100644 --- a/gcc/input.cc +++ b/gcc/input.cc @@ -79,6 +79,10 @@ public: void evict (); void set_content (const char *buf, size_t sz); + static void tune(size_t line_record_size_) { + line_record_size = line_record_size_; + } + private: /* These are information used to store a line boundary. */ class line_info @@ -116,7 +120,7 @@ public: bool goto_next_line (); static const size_t buffer_size = 4 * 1024; - static const size_t line_record_size = 100; + static size_t line_record_size; /* The number of time this file has been accessed. This is used to designate which file cache to evict from the cache @@ -192,6 +196,18 @@ public: }; +size_t file_cache_slot::line_record_size = 100; + +/* Tune file_cache. */ +void +file_cache::tune (size_t num_file_slots_, size_t lines) +{ + num_file_slots = num_file_slots_; + file_cache_slot::tune (lines); +} + +size_t file_cache::num_file_slots = 16; + static const char * find_end_of_line (const char *s, size_t len); diff --git a/gcc/input.h b/gcc/input.h index 18ccf4429fc5..a60afe80681f 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -161,13 +161,15 @@ class file_cache const char *buffer, size_t sz); + static void tune(size_t num_file_slots_, size_t lines); + private: file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count); file_cache_slot *add_file (const char *file_path); file_cache_slot *lookup_file (const char *file_path); private: - static const size_t num_file_slots = 16; + static size_t num_file_slots; file_cache_slot *m_file_slots; input_context m_input_context; }; diff --git a/gcc/params.opt b/gcc/params.opt index b5e7800d7e49..5d234a607c02 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -134,6 +134,14 @@ Maximum size (in bytes) of objects tracked bytewise by dead store elimination. Common Joined UInteger Var(param_early_inlining_insns) Init(6) Optimization Param Maximal estimated growth of function body caused by early inlining of single call. +-param=file-cache-files= +Common Joined UInteger Var(param_file_cache_files) Init(16) Param +Max number of files in the file cache. + +-param=file-cache-lines= +Common Joined UInteger Var(param_file_cache_lines) Init(100) Param +Max number of lines to index into file cache. + -param=fsm-scale-path-stmts= Common Joined UInteger Var(param_fsm_scale_path_stmts) Init(2) IntegerRange(1, 10) Param Optimization Scale factor to apply to the number of statements in a threading path crossing a loop backedge when comparing to max-jump-thread-duplication-stmts. diff --git a/gcc/toplev.cc b/gcc/toplev.cc index d45a12cab45f..e03af8b18056 100644 --- a/gcc/toplev.cc +++ b/gcc/toplev.cc @@ -2333,6 +2333,8 @@ toplev::main (int argc, char **argv) UNKNOWN_LOCATION, global_dc, targetm.target_option.override); + file_cache::tune (param_file_cache_files, param_file_cache_lines); + handle_common_deferred_options (); init_local_tick ();
[gcc r15-7327] Rebalance file_cache input line cache dynamically
https://gcc.gnu.org/g:4a992ecad0f302f69c4f6c42708c737eabaa60dc commit r15-7327-g4a992ecad0f302f69c4f6c42708c737eabaa60dc Author: Andi Kleen Date: Wed Dec 25 14:41:49 2024 -0800 Rebalance file_cache input line cache dynamically The input context file_cache maintains an array of anchors to speed up accessing lines before the previous line. The array has a fixed upper size and the algorithm relies on the linemap reporting the maximum number of lines in the file in advance to compute the position of each anchor in the cache. This doesn't work for C which doesn't know the maximum number of lines before the files has finished parsing. The code has a fallback for this, but it is quite inefficient and effectively defeats the cache, so many accesses have to go through most of the input buffer to compute line boundaries. For large files this can be very costly as demonstrated in PR118168. Use a different algorithm to maintain the cache without needing the maximum number of lines in advance. When the cache runs out of entries and the gap to the last line anchor gets too large, prune every second entry in the cache. This maintains even spacing of the line anchors without requiring the maximum index. For the original PR this moves the overhead of enabling -Wmisleading-indentation to 32% with the default cache size. With a 10k entry cache it becomes noise. cc1 -O0 -fsyntax-only mypy.c -quiet ran 1.03 ± 0.05 times faster than cc1 -O0 -fsyntax-only mypy.c -quiet -Wmisleading-indentation --param=file-cache-lines=1 1.09 ± 0.08 times faster than cc1 -O0 -fsyntax-only mypy.c -quiet -Wmisleading-indentation --param=file-cache-lines=1000 1.32 ± 0.07 times faster than cc1 -O0 -fsyntax-only mypy.c -quiet -Wmisleading-indentation The code could be further optimized, e.g. use the vectorized line search functions the preprocessor uses. Also it seems the input cache always reads the whole file into memory, so perhaps it should just be using file mmap if possible. gcc/ChangeLog: PR preprocessor/118168 * input.cc (file_cache_slot::get_next_line): Use new algorithm to maintain (file_cache_slot::read_line_num): Use binary search for lookup. Diff: --- gcc/input.cc | 132 +++ 1 file changed, 43 insertions(+), 89 deletions(-) diff --git a/gcc/input.cc b/gcc/input.cc index 8605202fed2c..b314328359f4 100644 --- a/gcc/input.cc +++ b/gcc/input.cc @@ -108,6 +108,11 @@ public: line_info () :line_num (0), start_pos (0), end_pos (0) {} + +static bool less_than(const line_info &a, const line_info &b) +{ + return a.line_num < b.line_num; +} }; bool needs_read_p () const; @@ -178,10 +183,8 @@ public: /* This is a record of the beginning and end of the lines we've seen while reading the file. This is useful to avoid walking the data from the beginning when we are asked to read a line that is - before LINE_START_IDX above. Note that the maximum size of this - record is line_record_size, so that the memory consumption - doesn't explode. We thus scale total_lines down to - line_record_size. */ + before LINE_START_IDX above. When the lines exceed line_record_size + this is scaled down dynamically, with the line_info becoming anchors. */ vec m_line_record; void offset_buffer (int offset) @@ -885,38 +888,33 @@ file_cache_slot::get_next_line (char **line, ssize_t *line_len) ++m_line_num; - /* Before we update our line record, make sure the hint about the - total number of lines of the file is correct. If it's not, then - we give up recording line boundaries from now on. */ - bool update_line_record = true; - if (m_line_num > m_total_lines) -update_line_record = false; - -/* Now update our line record so that re-reading lines from the + /* Now update our line record so that re-reading lines from the before m_line_start_idx is faster. */ - if (update_line_record - && m_line_record.length () < line_record_size) + size_t rlen = m_line_record.length (); + /* Only update when beyond the previously cached region. */ + if (rlen == 0 || m_line_record[rlen - 1].line_num < m_line_num) { - /* If the file lines fits in the line record, we just record all -its lines ...*/ - if (m_total_lines <= line_record_size - && m_line_num > m_line_record.length ()) + size_t spacing = rlen >= 2 ? + m_line_record[rlen - 1].line_num - m_line_record[rlen - 2].line_num : 1; + size_t delta = rlen >= 1 ? + m_line_num - m_line_record[rlen - 1].line_num : 1; + + /* If we're too far beyond drop half of the lines to rebalance. */ + if (rlen == line_record_size && delta >= spacing*2) +
[gcc r15-7328] Remove m_total_lines support from input cache
https://gcc.gnu.org/g:33acec612423efd2d9db9ffc808c4d103840dcd2 commit r15-7328-g33acec612423efd2d9db9ffc808c4d103840dcd2 Author: Andi Kleen Date: Wed Dec 25 14:42:09 2024 -0800 Remove m_total_lines support from input cache With the new cache maintenance algorithm we don't need the maximum number of lines anymore. Remove all the code for that. gcc/ChangeLog: PR preprocessor/118168 * input.cc (total_lines_num): Remove. (file_cache_slot::evict): Ditto. (file_cache_slot::create): Ditto. (file_cache_slot::set_content): Ditto. (file_cache_slot::file_cache_slot): Ditto. (file_cache_slot::dump): Ditto. Diff: --- gcc/input.cc | 45 + 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/gcc/input.cc b/gcc/input.cc index b314328359f4..64cb85eeed0e 100644 --- a/gcc/input.cc +++ b/gcc/input.cc @@ -165,16 +165,6 @@ public: means we've read no line so far. */ size_t m_line_num; - /* This is the total number of lines of the current file. At the - moment, we try to get this information from the line map - subsystem. Note that this is just a hint. When using the C++ - front-end, this hint is correct because the input file is then - completely tokenized before parsing starts; so the line map knows - the number of lines before compilation really starts. For e.g, - the C front-end, it can happen that we start emitting diagnostics - before the line map has seen the end of the file. */ - size_t m_total_lines; - /* Could this file be missing a trailing newline on its final line? Initially true (to cope with empty files), set to true/false as each line is read. */ @@ -317,25 +307,6 @@ expand_location_1 (const line_maps *set, return xloc; } -/* Return the total lines number that have been read so far by the - line map (in the preprocessor) so far. For languages like C++ that - entirely preprocess the input file before starting to parse, this - equals the actual number of lines of the file. */ - -static size_t -total_lines_num (const char *file_path) -{ - size_t r = 0; - location_t l = 0; - if (linemap_get_file_highest_location (line_table, file_path, &l)) -{ - gcc_assert (l >= RESERVED_LOCATION_COUNT); - expanded_location xloc = expand_location (l); - r = xloc.line; -} - return r; -} - /* Lookup the cache used for the content of a given file accessed by caret diagnostic. Return the found cached file, or NULL if no cached file was found. */ @@ -425,7 +396,6 @@ file_cache_slot::evict () m_line_num = 0; m_line_record.truncate (0); m_use_count = 0; - m_total_lines = 0; m_missing_trailing_newline = true; } @@ -525,7 +495,6 @@ file_cache_slot::create (const file_cache::input_context &in_context, /* Ensure that this cache entry doesn't get evicted next time add_file_to_cache_tab is called. */ m_use_count = ++highest_use_count; - m_total_lines = total_lines_num (file_path); m_missing_trailing_newline = true; @@ -572,17 +541,6 @@ file_cache_slot::set_content (const char *buf, size_t sz) fclose (m_fp); m_fp = nullptr; } - - /* Compute m_total_lines based on content of buffer. */ - m_total_lines = 0; - const char *line_start = m_data; - size_t remaining_size = sz; - while (const char *line_end = find_end_of_line (line_start, remaining_size)) -{ - ++m_total_lines; - remaining_size -= line_end + 1 - line_start; - line_start = line_end + 1; -} } /* file_cache's ctor. */ @@ -639,7 +597,7 @@ file_cache::lookup_or_add_file (const char *file_path) file_cache_slot::file_cache_slot () : m_use_count (0), m_file_path (NULL), m_fp (NULL), m_error (false), m_data (0), m_alloc_offset (0), m_size (0), m_nb_read (0), m_line_start_idx (0), - m_line_num (0), m_total_lines (0), m_missing_trailing_newline (true) + m_line_num (0), m_missing_trailing_newline (true) { m_line_record.create (0); } @@ -679,7 +637,6 @@ file_cache_slot::dump (FILE *out, int indent) const fprintf (out, "%*snb_read: %zi\n", indent, "", m_nb_read); fprintf (out, "%*sstart_line_idx: %zi\n", indent, "", m_line_start_idx); fprintf (out, "%*sline_num: %zi\n", indent, "", m_line_num); - fprintf (out, "%*stotal_lines: %zi\n", indent, "", m_total_lines); fprintf (out, "%*smissing_trailing_newline: %i\n", indent, "", (int)m_missing_trailing_newline); fprintf (out, "%*sline records (%i):\n",
[gcc r15-7330] Add a unit test for random access in the file cache
https://gcc.gnu.org/g:75ab30f77f6d8a555aa78472b45a75a508544c68 commit r15-7330-g75ab30f77f6d8a555aa78472b45a75a508544c68 Author: Andi Kleen Date: Sat Jan 25 22:48:29 2025 -0800 Add a unit test for random access in the file cache v2: Remove extra {} gcc/ChangeLog: * input.cc (check_line): New. (test_replacement): New function to test line caching. (input_cc_tests): Call test_replacement Diff: --- gcc/input.cc | 43 +++ 1 file changed, 43 insertions(+) diff --git a/gcc/input.cc b/gcc/input.cc index 3416c7cdd732..66a0ac6c5302 100644 --- a/gcc/input.cc +++ b/gcc/input.cc @@ -2301,6 +2301,48 @@ test_make_location_nonpure_range_endpoints (const line_table_case &case_) ASSERT_FALSE (IS_ADHOC_LOC (get_finish (not_aaa_eq_bbb))); } +/* Verify reading of a specific line LINENUM in TMP, FC. */ + +static void check_line (temp_source_file &tmp, file_cache &fc, int linenum) +{ + char_span line = fc.get_source_line (tmp.get_filename (), linenum); + int n; + /* get_buffer is not null terminated, but the sscanf stops after a number. */ + ASSERT_TRUE (sscanf (line.get_buffer (), "%d", &n) == 1); + ASSERT_EQ (n, linenum); +} + +/* Test file cache replacement. */ + +static void test_replacement () +{ + const int maxline = 1000; + + char *vec = XNEWVEC (char, maxline * 15); + char *p = vec; + int i; + for (i = 1; i <= maxline; i++) +p += sprintf (p, "%d\n", i); + + temp_source_file tmp (SELFTEST_LOCATION, ".txt", vec); + free (vec); + file_cache fc; + + for (i = 2; i <= maxline; i++) +{ + check_line (tmp, fc, i); + check_line (tmp, fc, i - 1); + if (i >= 10) + check_line (tmp, fc, i - 9); + if (i >= 350) /* Exceed the look behind cache. */ + check_line (tmp, fc, i - 300); +} + for (i = 5; i <= maxline; i += 100) +check_line (tmp, fc, i); + for (i = 1; i <= maxline; i++) +check_line (tmp, fc, i); +} + /* Verify reading of input files (e.g. for caret-based diagnostics). */ static void @@ -4251,6 +4293,7 @@ input_cc_tests () test_reading_source_line (); test_reading_source_buffer (); + test_replacement (); test_line_offset_overflow ();
[gcc r15-7329] Size input line cache based on file size
https://gcc.gnu.org/g:baf26fccfb51fa54fcf7c668b96cae4cdbe574b3 commit r15-7329-gbaf26fccfb51fa54fcf7c668b96cae4cdbe574b3 Author: Andi Kleen Date: Thu Dec 26 13:05:57 2024 -0800 Size input line cache based on file size While the input line cache size now tunable it's better if the compiler auto tunes it. Otherwise large files needing random file access will still have to search many lines to find the right lines. Add support for allocating one line anchor per hundred input lines. This means an overhead of ~235k per 1M input lines on 64bit, which seems reasonable. gcc/ChangeLog: PR preprocessor/118168 * input.cc (file_cache_slot::get_next_line): Implement dynamic sizing of m_line_record based on input length. * params.opt: (param_file_cache_lines): Set to 0 to size dynamically. Diff: --- gcc/input.cc | 11 --- gcc/params.opt | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/gcc/input.cc b/gcc/input.cc index 64cb85eeed0e..3416c7cdd732 100644 --- a/gcc/input.cc +++ b/gcc/input.cc @@ -189,7 +189,7 @@ public: }; -size_t file_cache_slot::line_record_size = 100; +size_t file_cache_slot::line_record_size = 0; /* Tune file_cache. */ void @@ -856,8 +856,13 @@ file_cache_slot::get_next_line (char **line, ssize_t *line_len) size_t delta = rlen >= 1 ? m_line_num - m_line_record[rlen - 1].line_num : 1; + size_t max_size = line_record_size; + /* One anchor per hundred input lines. */ + if (max_size == 0) + max_size = m_line_num / 100; + /* If we're too far beyond drop half of the lines to rebalance. */ - if (rlen == line_record_size && delta >= spacing*2) + if (rlen == max_size && delta >= spacing*2) { size_t j = 0; for (size_t i = 1; i < rlen; i += 2) @@ -867,7 +872,7 @@ file_cache_slot::get_next_line (char **line, ssize_t *line_len) spacing *= 2; } - if (rlen < line_record_size && delta >= spacing) + if (rlen < max_size && delta >= spacing) m_line_record.safe_push (file_cache_slot::line_info (m_line_num, m_line_start_idx, diff --git a/gcc/params.opt b/gcc/params.opt index 5d234a607c02..d84e35679e6d 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -136,10 +136,10 @@ Maximal estimated growth of function body caused by early inlining of single cal -param=file-cache-files= Common Joined UInteger Var(param_file_cache_files) Init(16) Param -Max number of files in the file cache. +Max number of files in the file cache. When 0 this is automatically sized. -param=file-cache-lines= -Common Joined UInteger Var(param_file_cache_lines) Init(100) Param +Common Joined UInteger Var(param_file_cache_lines) Init(0) Param Max number of lines to index into file cache. -param=fsm-scale-path-stmts=