This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]