VRP happily propagates SSA names even if they are used in
abnormal PHI nodes which later can lead to coalescing issues.
The following fixes that.

It also fixes the recursion abnormal edge added for setjmp.
setjmp is leaf (and not longjmp which I already fixed with
the original patch).

Bootstrap / regtest in progress on x86_64-unknown-linux-gnu.

Richard.

2013-04-22  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/57026
        * calls.c (special_function_p): setjmp and friends are ECF_LEAF.
        * builtins.def (BUILT_IN_SETJMP): Mark ATTR_NOTHROW_LEAF_LIST.
        * tree-vrp.c (simplify_conversion_using_ranges): Do not propagate
        from SSA names occuring in abnormal PHI nodes.

        * gcc.dg/torture/pr57026.c: New testcase.

Index: gcc/calls.c
===================================================================
*** gcc/calls.c (revision 198135)
--- gcc/calls.c (working copy)
*************** 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    (revision 198135)
--- gcc/builtins.def    (working copy)
*************** 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-vrp.c
===================================================================
*** gcc/tree-vrp.c      (revision 198135)
--- gcc/tree-vrp.c      (working copy)
*************** simplify_conversion_using_ranges (gimple
*** 8752,8758 ****
        || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
      return false;
    innerop = gimple_assign_rhs1 (def_stmt);
!   if (TREE_CODE (innerop) != SSA_NAME)
      return false;
  
    /* Get the value-range of the inner operand.  */
--- 8752,8759 ----
        || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
      return false;
    innerop = gimple_assign_rhs1 (def_stmt);
!   if (TREE_CODE (innerop) != SSA_NAME
!       || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop))
      return false;
  
    /* Get the value-range of the inner operand.  */
Index: gcc/testsuite/gcc.dg/torture/pr57026.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr57026.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr57026.c      (working copy)
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do compile } */
+ 
+ typedef struct __jmp_buf_tag { char buf[1024]; } jmp_buf[1];
+ extern int setjmp (jmp_buf);
+ extern int bar (unsigned int *);
+ extern jmp_buf *baz (void);
+ struct C { int c1; unsigned int c2, c3, c4; };
+ 
+ void
+ foo (struct C *x, const int *y, unsigned int *z, unsigned int e, unsigned int 
g)
+ {
+   unsigned int d = 0;
+   unsigned long f;
+   setjmp (*baz ());
+   f = d;
+   if ((x->c1 || x->c2) && g && (!e || d >= 8))
+     d = 16;
+   else
+     d = 8;
+   if ((!x->c3 && !x->c4 || *y == 0) && !e && bar (z))
+     *z = f;
+ }

Reply via email to