[PATCH] PR60092 - lower posix_memalign to make align-info accessible

Richard Biener rguenther@suse.de
Thu Feb 6 14:28:00 GMT 2014


This re-writes posix_memalign calls to

      posix_memalign (ptr, align, size);
      tem = *ptr;
      tem = __builtin_assume_aligned (align);
      *ptr = tem;

during CF lowering (yeah, ok ...) to make alignment info accessible
to SSA based analysis.

I have to adjust the added alias-31.c testcase again because with
the above we end up with

  <bb 2>:
  res_3 = *p_2(D);
  posix_memalign (&q.q1, 128, 512);
  _5 = MEM[(void *)&q];
  _6 = __builtin_assume_aligned (_5, 128);
  MEM[(void *)&q] = _6;
  posix_memalign (&q.q2, 128, 512);
  _17 = res_3 + res_3;
  _20 = _17 + 1;
  _23 = _20 + 2;
  q ={v} {CLOBBER};
  return _23;

after early DCE.  This is because DCE only has "baby" DSE built-in
and the store to MEM[(void *)&q] which it doesn't remove keeps
the rest live.  DSE removes the store and the DCE following it
the rest.

Not sure if more sophisticated lowering is wanted here.  Special-casing
&... operands to posix_memalign as stated in the PR, generating
for posix_memalign (&ptr, 128, 512);

  posix_memalign (&tem, 128, 512);
  reg = tem;
  reg = __builtin_assume_aligned (reg, 128);
  ptr = reg;

instead would be possible (hoping for ptr to become non-address-taken).

Bootstrap / regtest on x86_64-unknown-linux-gnu pending.

Thanks,
Richard.

2014-02-06  Richard Biener  <rguenther@suse.de>

	PR middle-end/60092
	* gimple-low.c (lower_builtin_posix_memalign): New function.
	(lower_stmt): Call it to lower posix_memalign in a way
	to make alignment info accessible.

	* gcc.dg/tree-ssa/alias-31.c: Adjust.
	* gcc.dg/vect/pr60092-2.c: New testcase.

Index: trunk/gcc/gimple-low.c
===================================================================
*** trunk.orig/gcc/gimple-low.c	2014-02-06 15:06:39.013419315 +0100
--- trunk/gcc/gimple-low.c	2014-02-06 15:12:39.116394523 +0100
*************** static void lower_gimple_bind (gimple_st
*** 83,88 ****
--- 83,89 ----
  static void lower_try_catch (gimple_stmt_iterator *, struct lower_data *);
  static void lower_gimple_return (gimple_stmt_iterator *, struct lower_data *);
  static void lower_builtin_setjmp (gimple_stmt_iterator *);
+ static void lower_builtin_posix_memalign (gimple_stmt_iterator *);
  
  
  /* Lower the body of current_function_decl from High GIMPLE into Low
*************** lower_stmt (gimple_stmt_iterator *gsi, s
*** 327,338 ****
  	  }
  
  	if (decl
! 	    && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
! 	    && DECL_FUNCTION_CODE (decl) == BUILT_IN_SETJMP)
  	  {
! 	    lower_builtin_setjmp (gsi);
! 	    data->cannot_fallthru = false;
! 	    return;
  	  }
  
  	if (decl && (flags_from_decl_or_type (decl) & ECF_NORETURN))
--- 328,346 ----
  	  }
  
  	if (decl
! 	    && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
  	  {
! 	    if (DECL_FUNCTION_CODE (decl) == BUILT_IN_SETJMP)
! 	      {
! 		lower_builtin_setjmp (gsi);
! 		data->cannot_fallthru = false;
! 		return;
! 	      }
! 	    else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_POSIX_MEMALIGN)
! 	      {
! 		lower_builtin_posix_memalign (gsi);
! 		return;
! 	      }
  	  }
  
  	if (decl && (flags_from_decl_or_type (decl) & ECF_NORETURN))
*************** lower_builtin_setjmp (gimple_stmt_iterat
*** 771,776 ****
--- 779,812 ----
    /* Remove the call to __builtin_setjmp.  */
    gsi_remove (gsi, false);
  }
+ 
+ /* Lower calls to posix_memalign to
+      posix_memalign (ptr, align, size);
+      tem = *ptr;
+      tem = __builtin_assume_aligned (align);
+      *ptr = tem;
+    so we can get at the alignment of *ptr 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_var (ptr_type_node, NULL);
+   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);
+   gimple_call_set_lhs (stmt, ptr);
+   gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
+   stmt = gimple_build_assign (fold_build2 (MEM_REF, ptr_type_node, pptr,
+ 					   build_int_cst (ptr_type_node, 0)),
+ 			      ptr);
+   gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
+ }
  
  
  /* Record the variables in VARS into function FN.  */
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/alias-31.c
===================================================================
*** trunk.orig/gcc/testsuite/gcc.dg/tree-ssa/alias-31.c	2014-02-06 15:11:55.881397499 +0100
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/alias-31.c	2014-02-06 15:12:39.117394523 +0100
***************
*** 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 -fdump-tree-dce2" } */
  
  extern int posix_memalign(void **memptr,
  			  __SIZE_TYPE__ alignment, __SIZE_TYPE__ size);
*************** int foo (int *p)
*** 20,24 ****
  /* There should be only one load from *p left.  All stores and all
     other loads should be removed.  */
  
! /* { dg-final { scan-tree-dump-times "\\\*\[^ \]" 1 "cddce1" } } */
! /* { dg-final { cleanup-tree-dump "cddce1" } } */
--- 20,24 ----
  /* There should be only one load from *p left.  All stores and all
     other loads should be removed.  */
  
! /* { dg-final { scan-tree-dump-times "\\\*\[^ \]" 1 "dce2" } } */
! /* { dg-final { cleanup-tree-dump "dce2" } } */
Index: trunk/gcc/testsuite/gcc.dg/vect/pr60092-2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/vect/pr60092-2.c	2014-02-06 15:15:10.167384123 +0100
***************
*** 0 ****
--- 1,25 ----
+ /* { dg-do compile } */
+ /* { dg-require-effective-target vect_int } */
+ 
+ int *foo (int n)
+ {
+   int *p;
+   int *q;
+   void *tem;
+   if (posix_memalign (&tem, 256, n * sizeof (int)) != 0)
+     return (void *)0;
+   p = (int *)tem;
+   if (posix_memalign (&tem, 256, n * sizeof (int)) != 0)
+     return (void *)0;
+   q = (int *)tem;
+   bar (q);
+   int i;
+   for (i = 0; i < n; ++i)
+     p[i] = q[i] + q[i];
+   return p;
+ }
+ 
+ /* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
+ /* { dg-final { scan-tree-dump-not "Peeling for alignment will be applied" "vect" } } */
+ /* { dg-final { scan-tree-dump-not "Vectorizing an unaligned access" "vect" } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */



More information about the Gcc-patches mailing list