Summary: | [8 Regression] GCC trunk miscompiles Perl / __sigsetjmp issue | ||
---|---|---|---|
Product: | gcc | Reporter: | pipcet |
Component: | tree-optimization | Assignee: | Richard Biener <rguenth> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | mikpelinux |
Priority: | P3 | Keywords: | wrong-code |
Version: | 8.0 | ||
Target Milestone: | 8.0 | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2017-08-21 00:00:00 | |
Attachments: |
creduce-minimized test case
executable testcase |
Created attachment 42008 [details]
executable testcase
Standalone executable testcase, exits 0 when compiled correctly, aborts or exits 1 otherwise. Fails for me with gcc-8 on x86_64-linux but works on same with gcc-7, gcc-6, and gcc-5.
I've investigated some more, and Mikael's bisection appears to confirm my investigation: The problem appears to be this chunk: @@ -2418,7 +2423,9 @@ compute_antic (void) inverted_post_order_compute (&postorder); auto_sbitmap worklist (last_basic_block_for_fn (cfun) + 1); - bitmap_ones (worklist); + bitmap_clear (worklist); + FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) + bitmap_set_bit (worklist, e->src->index); while (changed) { if (dump_file && (dump_flags & TDF_DETAILS)) It assumes there are always edges from function calls to the exit block, when the function call might exit nonlocally. However, cfganal.c:add_noreturn_fake_exit_edges is never called for functions that call setjmp, so such bbs are, wrongly, never visited by compute_antic. The brute-force method of disabling the tree/PRE pass for functions that call setjmp() appears to work and fix the issue, but I'm not sure that's the right way to go. Mine. So while there is one simple issue with the iteration, fix: @@ -2119,14 +2170,13 @@ static sbitmap has_abnormal_preds; static bool compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge) { - bool changed = false; bitmap_set_t S, old, ANTIC_OUT; bitmap_iterator bi; unsigned int bii; edge e; edge_iterator ei; - bool was_visited = BB_VISITED (block); + bool changed = ! BB_VISITED (block); old = ANTIC_OUT = S = NULL; BB_VISITED (block) = 1; @@ -2217,7 +2267,7 @@ compute_antic_aux (basic_block block, bo /* clean (ANTIC_IN (block)) is defered to after the iteration converged because it can cause non-convergence, see for example PR81181. */ - if (!was_visited || !bitmap_set_equal (old, ANTIC_IN (block))) + if (!bitmap_set_equal (old, ANTIC_IN (block))) changed = true; maybe_dump_sets: there is another issue as we think *_7 is antic and thus hoist the dereference before the _7 == 0 check which will optimize that away as not necessary in a later pass. Ah ... @@ -2396,9 +2446,6 @@ compute_antic (void) if (e->flags & EDGE_ABNORMAL) { bitmap_set_bit (has_abnormal_preds, block->index); - - /* We also anticipate nothing. */ - BB_VISITED (block) = 1; break; } I can confirm that fixes things here, thank you! Fixed. Author: rguenth Date: Mon Aug 21 13:18:35 2017 New Revision: 251226 URL: https://gcc.gnu.org/viewcvs?rev=251226&root=gcc&view=rev Log: 2017-08-21 Richard Biener <rguenther@suse.de> PR tree-optimization/81900 * tree-ssa-pre.c (compute_antic_aux): Properly compute changed for blocks with abnormal predecessors. (compute_antic): Do not set visited flag prematurely. * gcc.dg/torture/pr81900.c: New testcase. Added: trunk/gcc/testsuite/gcc.dg/torture/pr81900.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-ssa-pre.c *** Bug 81954 has been marked as a duplicate of this bug. *** Author: aldyh Date: Wed Sep 13 17:14:07 2017 New Revision: 252505 URL: https://gcc.gnu.org/viewcvs?rev=252505&root=gcc&view=rev Log: 2017-08-21 Richard Biener <rguenther@suse.de> PR tree-optimization/81900 * tree-ssa-pre.c (compute_antic_aux): Properly compute changed for blocks with abnormal predecessors. (compute_antic): Do not set visited flag prematurely. * gcc.dg/torture/pr81900.c: New testcase. Added: branches/range-gen2/gcc/testsuite/gcc.dg/torture/pr81900.c Modified: branches/range-gen2/gcc/ChangeLog branches/range-gen2/gcc/testsuite/ChangeLog branches/range-gen2/gcc/tree-ssa-pre.c |
Created attachment 42007 [details] creduce-minimized test case Hi, I'm having trouble running a GCC/trunk-compiled Perl; I first noticed the problem on my WebAssembly port, but I think I can reproduce it on x86_64 built from the standard GCC tree. I also think this is a GCC bug. After some editing, I've managed to generate a (somewhat) minimized testcase: Perl_croak() __attribute__((noreturn)); *Perl_sv_gets(); a() { __sigsetjmp(); char *b; if ((b = Perl_sv_gets()) == 0) Perl_croak("No Perl script found in input\n"); if (*b == '#') __asm__("" : : ""("badbad")); } The intended behaviour is that Perl_sv_gets() can return a NULL pointer, in which case the pointer isn't dereferenced and Perl_croak() is called instead. However, the assembly output I get is: xorl %eax, %eax call __sigsetjmp xorl %eax, %eax call Perl_sv_gets cmpb $35, (%rax) The call to Perl_croak has been removed, and the return value of Perl_sv_gets() is unconditionally dereferenced. That's wrong, right? I'm compiling with: $ ~/git/asmjs/subrepos/gcc/host-x86_64-pc-linux-gnu/gcc/xgcc -B /home/pip/git/asmjs/subrepos/gcc/host-x86_64-pc-linux-gnu/gcc/ -v -S -DPERL_CORE -fwrapv -std=c89 -O3 -fno-strict-aliasing -w -Wfatal-errors testcase.i -o tmp.s || exit 1 Reading specs from /home/pip/git/asmjs/subrepos/gcc/host-x86_64-pc-linux-gnu/gcc/specs COLLECT_GCC=/home/pip/git/asmjs/subrepos/gcc/host-x86_64-pc-linux-gnu/gcc/xgcc Target: x86_64-pc-linux-gnu Configured with: ./configure --target=x86_64-pc-linux-gnu --disable-bootstrap --enable-languages=c Thread model: posix gcc version 8.0.0 20170819 (experimental) (GCC) COLLECT_GCC_OPTIONS='-B' '/home/pip/git/asmjs/subrepos/gcc/host-x86_64-pc-linux-gnu/gcc/' '-v' '-S' '-D' 'PERL_CORE' '-fwrapv' '-std=c90' '-O3' '-fno-strict-aliasing' '-w' '-Wfatal-errors' '-o' 'tmp.s' '-mtune=generic' '-march=x86-64' /home/pip/git/asmjs/subrepos/gcc/host-x86_64-pc-linux-gnu/gcc/cc1 -fpreprocessed testcase.i -quiet -dumpbase testcase.i -mtune=generic -march=x86-64 -auxbase-strip tmp.s -O3 -Wfatal-errors -w -std=c90 -version -fwrapv -fno-strict-aliasing -o tmp.s GNU C89 (GCC) version 8.0.0 20170819 (experimental) (x86_64-pc-linux-gnu) compiled by GNU C version 6.4.0 20170724, GMP version 6.1.2, MPFR version 3.1.5, MPC version 1.0.3, isl version none GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 GNU C89 (GCC) version 8.0.0 20170819 (experimental) (x86_64-pc-linux-gnu) compiled by GNU C version 6.4.0 20170724, GMP version 6.1.2, MPFR version 3.1.5, MPC version 1.0.3, isl version none GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 Compiler executable checksum: d531daafd687d9500452e3b103d32887 COMPILER_PATH=/home/pip/git/asmjs/subrepos/gcc/host-x86_64-pc-linux-gnu/gcc/ LIBRARY_PATH=/home/pip/git/asmjs/subrepos/gcc/host-x86_64-pc-linux-gnu/gcc/:/lib/x86_64-linux-gnu/:/lib/../lib64/:/usr/lib/x86_64-linux-gnu/:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-B' '/home/pip/git/asmjs/subrepos/gcc/host-x86_64-pc-linux-gnu/gcc/' '-v' '-S' '-D' 'PERL_CORE' '-fwrapv' '-std=c90' '-O3' '-fno-strict-aliasing' '-w' '-Wfatal-errors' '-o' 'tmp.s' '-mtune=generic' '-march=x86-64' The call to sigsetjmp appears to be necessary to trigger the bug. Sorry if this is a duplicate or a known issue; right now, I don't have the time to investigate further. The call appears to be eliminated in a tree optimization pass, so I'm tentatively choosing that component.