Bug 57036 - [4.9 Regression] ice in update_ssa_across_abnormal_edges
Summary: [4.9 Regression] ice in update_ssa_across_abnormal_edges
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: 4.9.0
Assignee: Richard Biener
Depends on:
Blocks: 56982
  Show dependency treegraph
Reported: 2013-04-22 18:38 UTC by David Binderman
Modified: 2013-04-23 14:52 UTC (History)
1 user (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed: 2013-04-23 00:00:00

C source code (18.92 KB, text/x-csrc)
2013-04-22 18:38 UTC, David Binderman

Note You need to log in before you can comment on or make changes to this bug.
Description David Binderman 2013-04-22 18:38:22 UTC
Created attachment 29916 [details]
C source code

I just tried to compile the package hplip-3.13.4-1
on gcc-4.9 trunk dated 20130421 on an AMD x86_64 box.

The compiler said

ip/xjpg_dec.c:2612:32: internal compiler error: in update_ssa_across_abnormal_edges, at tree-inline.c:1852
                         memset (g->out_rows_ap[comp][row], ycc_white[comp], row_len);
0x94304d update_ssa_across_abnormal_edges
0x94304d copy_edges_for_bb
0x94304d copy_cfg_body
0x94304d copy_body
0x946ef3 expand_call_inline
0x946ef3 gimple_expand_calls_inline
0x946ef3 optimize_inline_calls(tree_node*)
0xd37356 early_inliner
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.

Preprocessed source code attached. Flag -O2 required.
Comment 1 Richard Biener 2013-04-23 10:36:40 UTC
I will have a look.
Comment 2 Richard Biener 2013-04-23 11:06:50 UTC
Reduced testcase:

extern void g (void);
extern __inline __attribute__ ((__always_inline__,__leaf__))
f ()
  g ();
struct __jmp_buf_tag *b;
int jpgDecode_convert (unsigned i)
  if (i != 0)
    f ();
  read_buf_open ();
  return _setjmp (b);

marking 'g' leaf as well fixes the ICE.

The inliner doesn't handle new abnormal edges appearing this way from
a 'leaf' function which isn't considered as possibly causing abnormal
goto edges.

I suppose all these setjmp ICEs are latent with carefully constructed
non-local goto testcases.
Comment 3 Richard Biener 2013-04-23 11:27:49 UTC
Closest equivalent non-local goto testcase that ICEs:

int j_;
int jpgDecode_convert (unsigned i)
  __label__ label;
  int j;

  inline void __attribute__((always_inline,leaf)) f(void)

  void __attribute__((noinline)) read_buf_open (void)
    goto label;

  if (i != 0)
    f ();
  j = j_;
  read_buf_open ();
  return j;

> ./cc1 -quiet -O0 t.i
t.i: In function 'jpgDecode_convert':
t.i:23:1: error: definition in block 4 does not dominate use in block 7
for SSA_NAME: j_2 in statement:
_3 = j_2;
t.i:23:1: internal compiler error: verify_ssa failed

same underlying issue I believe.
Comment 4 Richard Biener 2013-04-23 11:32:08 UTC
Either don't inline into functions receiving non-local gotos or remove
the ECF_LEAF handling from the call-may-do-longjmp predicate.
Comment 5 Richard Biener 2013-04-23 11:56:47 UTC
One idea was to mark calls with whether they may induce abnormal control flow
and when inlining, do not make abnormal edges off any calls in the function.
We still have to copy existing abnormal edges as within the callee there can
be abnormal control flow, too.  So there will be no way to later verify CFG
correctness because we lose "scoping" information of abnormal control flow.

Thus, the following simple patch is probably as good as we can get here ...
(in testing).

@@ -1866,7 +1870,8 @@ update_ssa_across_abnormal_edges (basic_
    debug stmts are left after a statement that must end the basic block.  */
 static bool
-copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb)
+copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb,
+                  bool can_make_abnormal_goto)
   basic_block new_bb = (basic_block) bb->aux;
   edge_iterator ei;
@@ -1921,7 +1926,11 @@ copy_edges_for_bb (basic_block bb, gcov_
          into a COMPONENT_REF which doesn't.  If the copy
          can throw, the original could also throw.  */
       can_throw = stmt_can_throw_internal (copy_stmt);
-      nonlocal_goto = stmt_can_make_abnormal_goto (copy_stmt);
+      /* If the call we inline cannot make abnormal goto do not add
+         additional abnormal edges but only retain those already present
+        in the original function body.  */
+      nonlocal_goto
+       = can_make_abnormal_goto && stmt_can_make_abnormal_goto (copy_stmt);
       if (can_throw || nonlocal_goto)
@@ -2270,10 +2279,12 @@ copy_cfg_body (copy_body_data * id, gcov
   last = last_basic_block;
   /* Now that we've duplicated the blocks, duplicate their edges.  */
+  bool can_make_abormal_goto = stmt_can_make_abnormal_goto (id->gimple_call);
   FOR_ALL_BB_FN (bb, cfun_to_copy)
     if (!blocks_to_copy
         || (bb->index > 0 && bitmap_bit_p (blocks_to_copy, bb->index)))
-      need_debug_cleanup |= copy_edges_for_bb (bb, count_scale, exit_block_map);
+      need_debug_cleanup |= copy_edges_for_bb (bb, count_scale, exit_block_map,
+                                              can_make_abormal_goto);
   if (new_entry)
Comment 6 Richard Biener 2013-04-23 14:52:33 UTC
Author: rguenth
Date: Tue Apr 23 14:36:02 2013
New Revision: 198192

URL: http://gcc.gnu.org/viewcvs?rev=198192&root=gcc&view=rev
2013-04-23  Richard Biener  <rguenther@suse.de>

	PR middle-end/57036
	* tree-inline.c (copy_edges_for_bb): Add can_make_abnormal_goto
	parameter, only add abnormal goto edges from the copied body
	if the call could perform abnormal gotos.
	(copy_cfg_body): Adjust.

	* gcc.dg/torture/pr57036-1.c: New testcase.
	* gcc.dg/torture/pr57036-2.c: Likewise.