On Wed, 12 Feb 2014, Richard Biener wrote:

> On Wed, 12 Feb 2014, Jakub Jelinek wrote:
> 
> > On Wed, Feb 12, 2014 at 10:30:01AM +0100, Richard Biener wrote:
> > > Bah.  I am testing the following.
> > 
> > But then there is no guarantee that ptr is aligned after the call.
> > char buf[32] __attribute__((aligned (32)));
> > int
> > foo (void)
> > {
> >   void *ptr = buf + 1;
> >   posix_memalign (&ptr, 32, -1);
> >   /* Assume posix_memalign has failed.  */
> >   return ((__UINTPTR_TYPE__)ptr) & 31;
> > }
> > 
> > This should return 1, but supposedly doesn't with the optimization.
> > So, either we need to revert the lowering, or perhaps do it only if
> > the original posix_memalign has a lhs and do it like:
> >   void *tmp;
> >   int res = posix_memalign (&tmp, align, size);
> >   if (!res)
> >     ptr = __builtin_assume_aligned (tmp, align);
> > or so (no need to initialize tmp and copy it back for the failure case,
> > but perhaps it would result in better code).
> 
> Yeah.  It seems to work modulo alias-31.c (checking what happens here,
> alias info looks good).  Prelimiary patch below.

Ok, I've analyzed what happens here and it's a pass ordering issue

          NEXT_PASS (pass_build_ealias);
          NEXT_PASS (pass_sra_early);
          NEXT_PASS (pass_fre);

PTA can figure out all points-to sets properly but when SRA
scalarizes the struct with the two posix_memaligned pointers
the replacements get written into SSA form and PHI nodes are
inserted for them (as assignment is now conditional).  That
process cannot reliably (and does never) set points-to info
for those vars.  FRE then fails to disambiguate.

Now, there is no reason why pass_build_ealias should be before
pass_sra_early - in fact that's a useless pessimization.

But as the testcase was supposed to test field-sensitive points-to
I chose to disable SRA for the testcase (and queue pass interchange
for 4.10 - unless you think it's ok now - I think it's harmless
and should only improve early FRE results when SRA happens).

Patch below in testing now.

Thanks,
Richard.

2014-02-12  Richard Biener  <rguent...@suse.de>

        PR middle-end/60092
        * gimple-low.c (lower_builtin_posix_memalign): Lower conditional
        of posix_memalign being successful.
        (lower_stmt): Restrict lowering of posix_memalign to when
        -ftree-bit-ccp is enabled.

        * gcc.dg/torture/pr60092.c: New testcase.
        * gcc.dg/tree-ssa/alias-31.c: Disable SRA.

Index: gcc/gimple-low.c
===================================================================
*** gcc/gimple-low.c    (revision 207714)
--- gcc/gimple-low.c    (working copy)
*************** lower_stmt (gimple_stmt_iterator *gsi, s
*** 336,342 ****
                data->cannot_fallthru = false;
                return;
              }
!           else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_POSIX_MEMALIGN)
              {
                lower_builtin_posix_memalign (gsi);
                return;
--- 336,343 ----
                data->cannot_fallthru = false;
                return;
              }
!           else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_POSIX_MEMALIGN
!                    && flag_tree_bit_ccp)
              {
                lower_builtin_posix_memalign (gsi);
                return;
*************** lower_builtin_setjmp (gimple_stmt_iterat
*** 781,817 ****
  }
  
  /* Lower calls to posix_memalign to
!      posix_memalign (ptr, align, size);
!      tem = *ptr;
!      tem = __builtin_assume_aligned (tem, align);
!      *ptr = tem;
     or to
       void *tem;
!      posix_memalign (&tem, align, size);
!      ttem = tem;
!      ttem = __builtin_assume_aligned (ttem, align);
!      ptr = tem;
     in case the first argument was &ptr.  That way we can get at the
     alignment of the heap pointer in CCP.  */
  
  static void
  lower_builtin_posix_memalign (gimple_stmt_iterator *gsi)
  {
!   gimple stmt = gsi_stmt (*gsi);
!   tree pptr = gimple_call_arg (stmt, 0);
!   tree align = gimple_call_arg (stmt, 1);
    tree ptr = create_tmp_reg (ptr_type_node, NULL);
    if (TREE_CODE (pptr) == ADDR_EXPR)
      {
        tree tem = create_tmp_var (ptr_type_node, NULL);
        TREE_ADDRESSABLE (tem) = 1;
!       gimple_call_set_arg (stmt, 0, build_fold_addr_expr (tem));
        stmt = gimple_build_assign (ptr, tem);
      }
    else
      stmt = gimple_build_assign (ptr,
                                fold_build2 (MEM_REF, ptr_type_node, pptr,
                                             build_int_cst (ptr_type_node, 0)));
    gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
    stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_ASSUME_ALIGNED),
                            2, ptr, align);
--- 782,828 ----
  }
  
  /* Lower calls to posix_memalign to
!      res = posix_memalign (ptr, align, size);
!      if (res == 0)
!        *ptr = __builtin_assume_aligned (*ptr, align);
     or to
       void *tem;
!      res = posix_memalign (&tem, align, size);
!      if (res == 0)
!        ptr = __builtin_assume_aligned (tem, align);
     in case the first argument was &ptr.  That way we can get at the
     alignment of the heap pointer in CCP.  */
  
  static void
  lower_builtin_posix_memalign (gimple_stmt_iterator *gsi)
  {
!   gimple stmt, call = gsi_stmt (*gsi);
!   tree pptr = gimple_call_arg (call, 0);
!   tree align = gimple_call_arg (call, 1);
!   tree res = gimple_call_lhs (call);
    tree ptr = create_tmp_reg (ptr_type_node, NULL);
    if (TREE_CODE (pptr) == ADDR_EXPR)
      {
        tree tem = create_tmp_var (ptr_type_node, NULL);
        TREE_ADDRESSABLE (tem) = 1;
!       gimple_call_set_arg (call, 0, build_fold_addr_expr (tem));
        stmt = gimple_build_assign (ptr, tem);
      }
    else
      stmt = gimple_build_assign (ptr,
                                fold_build2 (MEM_REF, ptr_type_node, pptr,
                                             build_int_cst (ptr_type_node, 0)));
+   if (res == NULL_TREE)
+     {
+       res = create_tmp_reg (integer_type_node, NULL);
+       gimple_call_set_lhs (call, res);
+     }
+   tree align_label = create_artificial_label (UNKNOWN_LOCATION);
+   tree noalign_label = create_artificial_label (UNKNOWN_LOCATION);
+   gimple cond = gimple_build_cond (EQ_EXPR, res, integer_zero_node,
+                                  align_label, noalign_label);
+   gsi_insert_after (gsi, cond, GSI_NEW_STMT);
+   gsi_insert_after (gsi, gimple_build_label (align_label), GSI_NEW_STMT);
    gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
    stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_ASSUME_ALIGNED),
                            2, ptr, align);
*************** lower_builtin_posix_memalign (gimple_stm
*** 821,826 ****
--- 832,838 ----
                                           build_int_cst (ptr_type_node, 0)),
                              ptr);
    gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
+   gsi_insert_after (gsi, gimple_build_label (noalign_label), GSI_NEW_STMT);
  }
  
  
Index: gcc/testsuite/gcc.dg/torture/pr60092.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr60092.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr60092.c      (working copy)
***************
*** 0 ****
--- 1,21 ----
+ /* { dg-do run } */
+ /* { dg-require-weak "" } */
+ 
+ typedef __SIZE_TYPE__ size_t;
+ extern int posix_memalign(void **memptr, size_t alignment, size_t size) 
__attribute__((weak));
+ extern void abort(void);
+ int
+ main (void)
+ {
+   void *p;
+   int ret;
+ 
+   if (!posix_memalign)
+     return 0;
+ 
+   p = (void *)&ret;
+   ret = posix_memalign (&p, sizeof (void *), -1);
+   if (p != (void *)&ret)
+     abort ();
+   return 0;
+ }
Index: gcc/testsuite/gcc.dg/tree-ssa/alias-31.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/alias-31.c    (revision 207714)
--- gcc/testsuite/gcc.dg/tree-ssa/alias-31.c    (working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-cddce1" } */
  
  extern int posix_memalign(void **memptr,
                          __SIZE_TYPE__ alignment, __SIZE_TYPE__ size);
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O2 -fno-tree-sra -fdump-tree-cddce1" } */
  
  extern int posix_memalign(void **memptr,
                          __SIZE_TYPE__ alignment, __SIZE_TYPE__ size);

Reply via email to