The following patch finally makes setjmp LEAF after I figured
what breaks the original testcase.  The inliner has an overzealous
assert that there cannot be new abnormal edges into the entry
block (the block preceeding the call we inline).  But that can
perfectly well happen with

bb1:
  setjmp ();

bb2:
  foo ();

when foo can transfer control flow to bb1.  And the code can
perfectly well handle the situation.

The patch avoids the odd abnormal edge we have now from each
setjmp call to itself.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

2013-05-07  Richard Biener  <rguent...@suse.de>

        * calls.c (special_function_p): setjmp-like functions are leaf.
        * builtins.def (BUILT_IN_SETJMP): setjmp is leaf.
        * tree-inline.c (update_ssa_across_abnormal_edges): Remove assert.

Index: gcc/calls.c
===================================================================
*** gcc/calls.c.orig    2013-05-03 11:29:16.000000000 +0200
--- gcc/calls.c 2013-05-07 11:36:30.886404048 +0200
*************** special_function_p (const_tree fndecl, i
*** 545,551 ****
                  && ! strcmp (tname, "sigsetjmp"))
              || (tname[1] == 'a'
                  && ! strcmp (tname, "savectx")))
!           flags |= ECF_RETURNS_TWICE;
  
          if (tname[1] == 'i'
              && ! strcmp (tname, "siglongjmp"))
--- 545,551 ----
                  && ! strcmp (tname, "sigsetjmp"))
              || (tname[1] == 'a'
                  && ! strcmp (tname, "savectx")))
!           flags |= ECF_RETURNS_TWICE | ECF_LEAF;
  
          if (tname[1] == 'i'
              && ! strcmp (tname, "siglongjmp"))
*************** special_function_p (const_tree fndecl, i
*** 557,563 ****
                   && ! strcmp (tname, "vfork"))
               || (tname[0] == 'g' && tname[1] == 'e'
                   && !strcmp (tname, "getcontext")))
!       flags |= ECF_RETURNS_TWICE;
  
        else if (tname[0] == 'l' && tname[1] == 'o'
               && ! strcmp (tname, "longjmp"))
--- 557,563 ----
                   && ! strcmp (tname, "vfork"))
               || (tname[0] == 'g' && tname[1] == 'e'
                   && !strcmp (tname, "getcontext")))
!       flags |= ECF_RETURNS_TWICE | ECF_LEAF;
  
        else if (tname[0] == 'l' && tname[1] == 'o'
               && ! strcmp (tname, "longjmp"))
Index: gcc/builtins.def
===================================================================
*** gcc/builtins.def.orig       2013-05-03 11:29:16.000000000 +0200
--- gcc/builtins.def    2013-05-07 11:36:30.887404061 +0200
*************** DEF_LIB_BUILTIN        (BUILT_IN_REALLOC
*** 732,738 ****
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR, 
ATTR_NORETURN_NOTHROW_LEAF_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN_ADDRESS, "return_address", 
BT_FN_PTR_UINT, ATTR_LEAF_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, 
ATTR_NULL)
! DEF_GCC_BUILTIN        (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_NULL)
  DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRFMON, "strfmon", 
BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4)
  DEF_LIB_BUILTIN        (BUILT_IN_STRFTIME, "strftime", 
BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0)
  DEF_GCC_BUILTIN        (BUILT_IN_TRAP, "trap", BT_FN_VOID, 
ATTR_NORETURN_NOTHROW_LEAF_LIST)
--- 732,738 ----
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR, 
ATTR_NORETURN_NOTHROW_LEAF_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN_ADDRESS, "return_address", 
BT_FN_PTR_UINT, ATTR_LEAF_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, 
ATTR_NULL)
! DEF_GCC_BUILTIN        (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, 
ATTR_NOTHROW_LEAF_LIST)
  DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRFMON, "strfmon", 
BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4)
  DEF_LIB_BUILTIN        (BUILT_IN_STRFTIME, "strftime", 
BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0)
  DEF_GCC_BUILTIN        (BUILT_IN_TRAP, "trap", BT_FN_VOID, 
ATTR_NORETURN_NOTHROW_LEAF_LIST)
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c.orig      2013-05-07 12:35:12.000000000 +0200
--- gcc/tree-inline.c   2013-05-07 12:35:19.286140199 +0200
*************** update_ssa_across_abnormal_edges (basic_
*** 1839,1846 ****
  
            phi = gsi_stmt (si);
  
!           /* There shouldn't be any PHI nodes in the ENTRY_BLOCK.  */
!           gcc_assert (!e->dest->aux);
  
            gcc_assert ((e->flags & EDGE_EH)
                        || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)));
--- 1839,1846 ----
  
            phi = gsi_stmt (si);
  
!           /* For abnormal goto/call edges the receiver can be the
!              ENTRY_BLOCK.  Do not assert this cannot happen.  */
  
            gcc_assert ((e->flags & EDGE_EH)
                        || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)));

Reply via email to