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

            Bug ID: 85449
           Summary: [8 Regression] Wrong specialization is called in self
                    recursive functions after r259319
           Product: gcc
           Version: 8.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ipa
          Assignee: unassigned at gcc dot gnu.org
          Reporter: tnfchris at gcc dot gnu.org
                CC: marxin at gcc dot gnu.org
  Target Milestone: ---

Created attachment 43977
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=43977&action=edit
preprocessed file

After commit r259319 IPA seems to be calling the wrong specialized function.

The testcase comes from the following library
https://github.com/akheron/jansson, specifically this file
https://github.com/akheron/jansson/blob/master/src/dump.c

I have not been able to reduce it yet as I have no real easy way to check when
it does the replacement wrong but I have attached a `.i` file and issue can be
reproduced using it by using `-Ofast` or `-O3`.

This is what I have been able to tell so far. The issue is caused by a self
recursive call in the function

static int do_dump(const json_t *json, size_t flags, int depth,
                   json_dump_callback_t dump, void *data)

where json_dump_callback_t dump is a function pointer to local functions. There
are only two call sites for do_dump other than itself.

char *json_dumps(const json_t *json, size_t flags)
{
    strbuffer_t strbuff;
    char *result;

    if(strbuffer_init(&strbuff))
        return NULL;

    if(json_dump_callback(json, dump_to_strbuffer, (void *)&strbuff, flags))
        result = NULL;
    else
        result = jsonp_strdup(strbuffer_value(&strbuff));


    strbuffer_close(&strbuff);
    return result;

}


int json_dumpf(const json_t *json, FILE *output, size_t flags)

{
    return json_dump_callback(json, dump_to_file, (void *)output, flags);
}

where dump_to_strbuffer expects to write into a memory buffer and dump_to_file
writing to an actual file.

So IPA decides to create 8 specializations for this function (whereas before
this patch it created 4.), it creates them by amongst others inlining the calls
to these two dump callbacks, and eventually even inlines the callbacks
themselves.

The problematic specialization occurs for the function {{do_dumps}} which has
amonst others

.LVL289:
        .loc 1 368 24
        fmov    x4, d8
        mov     x3, x19
        mov     w2, 1
        mov     x1, x21
        bl      do_dump

The first specialization occurs when a helper function {{dump_indent}} is
inline, creating {{do_dumps.constprop.4}} which is supposed to still take the
callbacks as arguments.

and indeed looking at the assembly is shows

json_dumps:
...
.L260:
        adrp    x2, dump_to_strbuffer
        mov     x1, x20
        mov     x0, x19
        add     x3, sp, 40

.LVL440:
        add     x2, x2, :lo12:dump_to_strbuffer
        bl      do_dump.constprop.4


so far so good. But the recursive call to do_dump in the specialized
constprop.4 version inexplicably calls do_dump.constprop.5 in some (2 out of
the many) cases.

Where do_dump.constprop.5 is a more specialized version of constprop.4 which
also inlined the dump_to_file function.

do_dump.constprop.5:
...
        add     x0, x0, :lo12:.LC14
        mov     x1, 4
        bl      fwrite

So the initial callback which is passed is dump_to_strbuffer is ignored and a
call to dump_to_file is essentially made. causing a segfault.

The first place this seems to go wrong is `.i.075i.cp`

looking at the dependencies of `constprop.4/82` which is supposed to be the
generic clone

do_dump.constprop.4/82 (do_dump.constprop) @0x7ff4280128a0
  ...

  Calls: json_integer_value/55 (119292717 (estimated locally),0.11 per call)
snprintf/56 (119292717 (estimated locally),0.11 per call) json_real_value/57
(119292717 (estimated locally),0.11 per call) jsonp_dtostr/58 (119292717
(estimated locally),0.11 per call) json_string_value/59 (119292717 (estimated
locally),0.11 per call) dump_string/39 (119292717 (estimated locally),0.11 per
call) json_array_size/60 (116799499 (estimated locally),0.11 per call)
dump_indent.constprop/85 (56497842 (estimated locally),0.05 per call)
json_array_get/61 (341791464 (estimated locally),0.32 per call)
do_dump.constprop/83 (341791464 (estimated locally),0.32 per call)
dump_indent.constprop/85 (244621272 (estimated locally),0.23 per call)
dump_indent/38 (70872647 (estimated locally),0.07 per call) json_object_iter/62
(116799499 (estimated locally),0.11 per call) dump_indent.constprop/85
(79811293 (estimated locally),0.07 per call) json_object_size/63 (26063814
(estimated locally),0.02 per call) jsonp_malloc/64 (26063814 (estimated
locally),0.02 per call) jsonp_object_iter_fullkey/65 (209930993 (estimated
locally),0.20 per call) json_object_iter_next/66 (209930993 (estimated
locally),0.20 per call) __assert_fail/67 (10379 (estimated locally),0.00 per
call) qsort/69 (25936149 (estimated locally),0.02 per call) json_object_get/70
(181163084 (estimated locally),0.17 per call) __assert_fail/67 (72465
(estimated locally),0.00 per call) dump_string/39 (181090619 (estimated
locally),0.17 per call) do_dump.constprop/83 (175404373 (estimated
locally),0.16 per call) <--- this reference is wrong

jsonp_free/71 (11193943 (estimated locally),0.01 per call)
dump_indent.constprop/85 (110256487 (estimated locally),0.10 per call)
jsonp_free/71 (7036340 (estimated locally),0.01 per call) dump_indent/38
(56065903 (estimated locally),0.05 per call) jsonp_free/71 (1760469 (estimated
locally),0.00 per call) jsonp_free/71 (5872931 (estimated locally),0.01 per
call) json_object_iter_next/66 (309742814 (estimated locally),0.29 per call)
json_object_iter_key/72 (309742814 (estimated locally),0.29 per call)
dump_string/39 (309742814 (estimated locally),0.29 per call)
json_object_iter_value/73 (298406227 (estimated locally),0.28 per call)
do_dump.constprop/83 (298406227 (estimated locally),0.28 per call)
dump_indent.constprop/85 (228688039 (estimated locally),0.21 per call)
dump_indent/38 (50108559 (estimated locally),0.05 per call)

  ...

But I have not figured out why it thinks this.

Reply via email to