This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR57036
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 23 Apr 2013 16:32:31 +0200 (CEST)
- Subject: [PATCH] Fix PR57036
This fixes PR57036 which is inlining of a ECF_LEAF function
(which cannot perform abnormal control flow into the caller)
which in turn has a function call that might abnormally transfer
control flow. The fix is to avoid adding _extra_ abnormal
edges from such calls to possible receivers in the caller
but leave existing abnormal edges in the copied callee in place.
There isn't a way to otherwise honor both always_inline and
leaf as we might transform the caller function body in a way
that would be invalid if it were allowed to transfer control
flow abnormally.
It's still valid to have abnormal control flow transfer completely
inside a leaf function of course and we may not destroy abnormal
edges resulting from that.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard.
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.
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c (revision 198190)
--- gcc/tree-inline.c (working copy)
*************** update_ssa_across_abnormal_edges (basic_
*** 1866,1872 ****
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)
{
basic_block new_bb = (basic_block) bb->aux;
edge_iterator ei;
--- 1866,1873 ----
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,
! bool can_make_abnormal_goto)
{
basic_block new_bb = (basic_block) bb->aux;
edge_iterator ei;
*************** copy_edges_for_bb (basic_block bb, gcov_
*** 1921,1927 ****
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 (can_throw || nonlocal_goto)
{
--- 1922,1932 ----
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);
! /* 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)
{
*************** copy_cfg_body (copy_body_data * id, gcov
*** 2270,2279 ****
last = last_basic_block;
/* Now that we've duplicated the blocks, duplicate their edges. */
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);
if (new_entry)
{
--- 2275,2287 ----
last = last_basic_block;
/* Now that we've duplicated the blocks, duplicate their edges. */
+ bool can_make_abormal_goto
+ = id->gimple_call && 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,
! can_make_abormal_goto);
if (new_entry)
{
Index: gcc/testsuite/gcc.dg/torture/pr57036-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr57036-1.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr57036-1.c (revision 0)
***************
*** 0 ****
--- 1,16 ----
+ /* { dg-do compile } */
+
+ 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);
+ }
Index: gcc/testsuite/gcc.dg/torture/pr57036-2.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr57036-2.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr57036-2.c (revision 0)
***************
*** 0 ****
--- 1,25 ----
+ /* { dg-do compile } */
+
+ int j_;
+ int jpgDecode_convert (unsigned i)
+ {
+ __label__ label;
+ int j;
+
+ inline void __attribute__((always_inline,leaf)) f(void)
+ {
+ g();
+ }
+
+ void __attribute__((noinline)) read_buf_open (void)
+ {
+ goto label;
+ }
+
+ if (i != 0)
+ f ();
+ j = j_;
+ read_buf_open ();
+ label:
+ return j;
+ }