This fixes PR47025, __builtin_va_end is preventing dead store
elimination and __builtin_va_start is an escape point for the
valist.

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

Richard.

2011-09-06  Richard Guenther  <rguent...@suse.de>

        PR tree-optimization/47025
        * tree-ssa-alias.c (ref_maybe_used_by_call_p_1): BUILT_IN_VA_END
        uses nothing.
        (call_may_clobber_ref_p_1): BUILT_IN_VA_END is a barrier like
        BUILT_IN_FREE.
        (stmt_kills_ref_p_1): BUILT_IN_VA_END kills what its argument
        definitely points to.
        * tree-ssa-structalias.c (find_func_aliases_for_builtin_call):
        BUILT_IN_VA_START doesn't let its va_list argument escape.
        * tree-ssa-dce.c (propagate_necessity): BUILT_IN_VA_END does
        not make any previous stores necessary.

Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig   2011-09-06 16:24:16.000000000 +0200
--- gcc/tree-ssa-alias.c        2011-09-06 16:28:48.000000000 +0200
*************** ref_maybe_used_by_call_p_1 (gimple call,
*** 1254,1259 ****
--- 1254,1260 ----
        case BUILT_IN_SINCOSF:
        case BUILT_IN_SINCOSL:
        case BUILT_IN_ASSUME_ALIGNED:
+       case BUILT_IN_VA_END:
          return false;
        /* __sync_* builtins and some OpenMP builtins act as threading
           barriers.  */
*************** call_may_clobber_ref_p_1 (gimple call, a
*** 1518,1523 ****
--- 1519,1525 ----
           the call has to serve as a barrier for moving loads and stores
           across it.  */
        case BUILT_IN_FREE:
+       case BUILT_IN_VA_END:
          {
            tree ptr = gimple_call_arg (call, 0);
            return ptr_deref_may_alias_ref_p_1 (ptr, ref);
*************** stmt_kills_ref_p_1 (gimple stmt, ao_ref
*** 1763,1772 ****
                              / BITS_PER_UNIT)))
                    return true;
                }
            }
          default:;
          }
- 
      }
    return false;
  }
--- 1765,1787 ----
                              / BITS_PER_UNIT)))
                    return true;
                }
+             break;
+           }
+ 
+         case BUILT_IN_VA_END:
+           {
+             tree ptr = gimple_call_arg (stmt, 0);
+             if (TREE_CODE (ptr) == ADDR_EXPR)
+               {
+                 tree base = ao_ref_base (ref);
+                 if (TREE_OPERAND (ptr, 0) == base)
+                   return true;
+               }
+             break;
            }
+ 
          default:;
          }
      }
    return false;
  }
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c.orig     2011-09-06 16:23:29.000000000 +0200
--- gcc/tree-ssa-structalias.c  2011-09-06 16:24:18.000000000 +0200
*************** find_func_aliases_for_builtin_call (gimp
*** 4187,4213 ****
         mode as well.  */
        case BUILT_IN_VA_START:
        {
          if (in_ipa_mode)
            {
-             tree valist = gimple_call_arg (t, 0);
-             struct constraint_expr rhs, *lhsp;
-             unsigned i;
-             /* The va_list gets access to pointers in variadic
-                arguments.  */
              fi = lookup_vi_for_tree (cfun->decl);
-             gcc_assert (fi != NULL);
-             get_constraint_for (valist, &lhsc);
-             do_deref (&lhsc);
              rhs = get_function_part_constraint (fi, ~0);
              rhs.type = ADDRESSOF;
-             FOR_EACH_VEC_ELT (ce_s, lhsc, i, lhsp)
-                 process_constraint (new_constraint (*lhsp, rhs));
-             VEC_free (ce_s, heap, lhsc);
-             /* va_list is clobbered.  */
-             make_constraint_to (get_call_clobber_vi (t)->id, valist);
-             return true;
            }
!         break;
        }
        /* va_end doesn't have any effect that matters.  */
        case BUILT_IN_VA_END:
--- 4187,4218 ----
         mode as well.  */
        case BUILT_IN_VA_START:
        {
+         tree valist = gimple_call_arg (t, 0);
+         struct constraint_expr rhs, *lhsp;
+         unsigned i;
+         get_constraint_for (valist, &lhsc);
+         do_deref (&lhsc);
+         /* The va_list gets access to pointers in variadic
+            arguments.  Which we know in the case of IPA analysis
+            and otherwise are just all nonlocal variables.  */
          if (in_ipa_mode)
            {
              fi = lookup_vi_for_tree (cfun->decl);
              rhs = get_function_part_constraint (fi, ~0);
              rhs.type = ADDRESSOF;
            }
!         else
!           {
!             rhs.var = nonlocal_id;
!             rhs.type = ADDRESSOF;
!             rhs.offset = 0;
!           }
!         FOR_EACH_VEC_ELT (ce_s, lhsc, i, lhsp)
!           process_constraint (new_constraint (*lhsp, rhs));
!         VEC_free (ce_s, heap, lhsc);
!         /* va_list is clobbered.  */
!         make_constraint_to (get_call_clobber_vi (t)->id, valist);
!         return true;
        }
        /* va_end doesn't have any effect that matters.  */
        case BUILT_IN_VA_END:
Index: gcc/tree-ssa-dce.c
===================================================================
*** gcc/tree-ssa-dce.c.orig     2011-09-06 16:23:29.000000000 +0200
--- gcc/tree-ssa-dce.c  2011-09-06 16:24:18.000000000 +0200
*************** propagate_necessity (struct edge_list *e
*** 836,841 ****
--- 836,842 ----
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_MALLOC
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_CALLOC
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_FREE
+                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_VA_END
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_SAVE
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE

Reply via email to