https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94311

--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I think the problem is just we ran out of the locations.
We hit both
  if (start_location >= LINE_MAP_MAX_LOCATION)
    /* We ran out of line map space.   */
    start_location = 0;
in linemap_add and
    overflowed:
      /* Remember we overflowed.  */
      set->highest_line = set->highest_location = LINE_MAP_MAX_LOCATION - 1;
      /* No column numbers!  */
      set->max_column_hint = 1;
      return 0;
in linemap_line_start.  While the latter is not that bad, we just get
UNKNOWN_LOCATION, the former is really bad, it just ignores whatever was before
and starts reusing those locations for something different.
Both of these spots are encountered once during this lto1 compilation, on a
total of 149763 linemap_add calls and 267678 linemap_line_start calls, so I'm
surprised that it got so quickly depleted.
Now, looking why it happens so quickly, I think because the line numbers in the
same file keep jumping back and forth extremely often, I see
#0  linemap_line_start (set=0x7ffff7ffb000, to_line=256, max_column_hint=17) at
../../libcpp/include/line-map.h:952
#1  0x0000000000d50886 in lto_location_cache::apply_location_cache
(this=0x2dbb868) at ../../gcc/lto-streamer-in.c:191
#2  0x0000000000d50de2 in stream_input_location_now (bp=<optimized out>,
data_in=0x2dbb840) at ../../gcc/lto-streamer-in.c:301
#3  0x000000000193d125 in input_gimple_stmt (tag=365, data_in=0x2dbb840,
ib=0x7fffffffcef0) at ../../gcc/gimple-streamer-in.c:111
#4  input_bb (ib=0x7fffffffcef0, tag=365, data_in=0x2dbb840, fn=0x7fffe7bd6630,
count_materialization_scale=<optimized out>)
    at ../../gcc/gimple-streamer-in.c:283
and
#0  linemap_line_start (set=0x7ffff7ffb000, to_line=8483, max_column_hint=8) at
../../libcpp/include/line-map.h:952
#1  0x0000000000d50886 in lto_location_cache::apply_location_cache
(this=0x2dbb868) at ../../gcc/lto-streamer-in.c:191
#2  0x0000000000d50de2 in stream_input_location_now (bp=<optimized out>,
data_in=0x2dbb840) at ../../gcc/lto-streamer-in.c:301
#3  0x000000000193d125 in input_gimple_stmt (tag=365, data_in=0x2dbb840,
ib=0x7fffffffcef0) at ../../gcc/gimple-streamer-in.c:111
#4  input_bb (ib=0x7fffffffcef0, tag=365, data_in=0x2dbb840, fn=0x7fffe7bd6630,
count_materialization_scale=<optimized out>)
    at ../../gcc/gimple-streamer-in.c:283
alternating all the time for quite a while (minor details on the exact to_line
numbers, but the important is going back and forth between 8NNN and 2NN
numbers).
Now, the backwards jumps result in the linemap_add calls too from (because
line_delta is negative), and when doing the big step forward, while line_delta
is large (larger than 8000).
      || (line_delta > 10
          && line_delta * map->m_column_and_range_bits > 1000)
is false as map->m_column_and_range_bits is 0, but one of the later condition
is true, so we add_map too, but then run into:
      /* Allocate the new line_map.  However, if the current map only has a
         single line we can sometimes just increase its column_bits instead. */
      if (line_delta < 0
          || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
          || SOURCE_COLUMN (map, highest) >= (1U << (column_bits - range_bits))
          || ( /* We can't reuse the map if the line offset is sufficiently
                  large to cause overflow when computing location_t values.  */
              (to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
              >= (((uint64_t) 1)
                  << (CHAR_BIT * sizeof (linenum_type) - column_bits)))
          || range_bits < map->m_range_bits)
line_delta is > 8000, last_line is equal to ORDINARY_MAP_STARTING_LINE_NUMBER
(map), in the previous linemap_line_start we've called linemap_add because
line_delta was negative, column_bits and range_bits and SOURCE_COLUMN (map,
highest) are all 0 and to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map) is
that 8000-ish number, which is smaller than 1ULL << (8 * 4 - 0) which is 4G.

I think to resolve this we can do multiple things:
1) if possible avoid the stream_input_location_now on each gimple stmt,
that seems to be the killer.
The rationale is:
  /* Read location information.  Caching here makes no sense until streamer
     cache can handle the following gimple_set_block.  */
  gimple_set_location (stmt, stream_input_location_now (&bp, data_in));

  /* Read lexical block reference.  */
  gimple_set_block (stmt, stream_read_tree (ib, data_in));
So perhaps have a way add the block to the location cache, and maybe also avoid
it on PHIs too?

And/or try to limit the to_line jumps much more if we are already at the no
column bits stage.
I can try to create a small testcase tomorrow...

Reply via email to