On Thu, 6 Feb 2014, Jakub Jelinek wrote:
> On Thu, Feb 06, 2014 at 02:21:01PM +0100, Richard Biener wrote:
> > + /* We marking allocated storage local, we deal with it becoming
> > + global by escaping and setting of vars_contains_escaped_heap. */
>
> Did you mean By marking ..., or something else?
"We are marking ..." cut&pasted and fixed both cases.
> > + extern int posix_memalign(void **memptr,
> > + __SIZE_TYPE__ alignment, __SIZE_TYPE__ size);
> > +
> > + int foo (int *p)
> > + {
> > + int res = *p;
> > + int *q;
> > + posix_memalign ((void **)&q, 128, 128 * sizeof (int));
>
> Do you really want to have strict aliasing violations in the testcase?
> I think one has to take address of a void * variable and if you want
> int *, then cast to int * afterwards.
Sure, I'll fix that (it doesn't matter for GCC luckily ;)). I still
expect user code to be lazy ... (which is why GCC treats all pointer
types as having the same alias set)
> Also, I think for posix_memalign
> you really should be checking return value of the function.
Yeah.
Like the following - will commit after re-bootstrapping together
with the 3rd followup.
Richard.
2014-02-06 Richard Biener <[email protected]>
PR middle-end/60092
* builtin-types.def (BT_FN_INT_PTRPTR_SIZE_SIZE): Add.
* builtins.def (BUILT_IN_POSIX_MEMALIGN): Likewise.
* tree-ssa-structalias.c (find_func_aliases_for_builtin_call):
Handle BUILT_IN_POSIX_MEMALIGN.
(find_func_clobbers): Likewise.
* tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Likewise.
(call_may_clobber_ref_p_1): Likewise.
* gcc.dg/tree-ssa/alias-30.c: New testcase.
* gcc.dg/tree-ssa/alias-31.c: Likewise.
Index: gcc/builtin-types.def
===================================================================
*** gcc/builtin-types.def.orig 2014-02-06 12:43:09.585012064 +0100
--- gcc/builtin-types.def 2014-02-06 12:43:34.435010353 +0100
*************** DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_
*** 429,434 ****
--- 429,435 ----
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I4_INT, BT_VOID, BT_VOLATILE_PTR, BT_I4,
BT_INT)
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I8_INT, BT_VOID, BT_VOLATILE_PTR, BT_I8,
BT_INT)
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR,
BT_I16, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_INT_PTRPTR_SIZE_SIZE, BT_INT, BT_PTR_PTR, BT_SIZE,
BT_SIZE)
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
Index: gcc/builtins.def
===================================================================
*** gcc/builtins.def.orig 2014-02-06 12:43:09.586012064 +0100
--- gcc/builtins.def 2014-02-06 15:06:39.716419267 +0100
*************** DEF_GCC_BUILTIN (BUILT_IN_POPCOUN
*** 755,760 ****
--- 755,761 ----
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTIMAX, "popcountimax",
BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTL, "popcountl", BT_FN_INT_ULONG,
ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTLL, "popcountll",
BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+ DEF_EXT_LIB_BUILTIN (BUILT_IN_POSIX_MEMALIGN, "posix_memalign",
BT_FN_INT_PTRPTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_GCC_BUILTIN (BUILT_IN_PREFETCH, "prefetch",
BT_FN_VOID_CONST_PTR_VAR, ATTR_NOVOPS_LEAF_LIST)
DEF_LIB_BUILTIN (BUILT_IN_REALLOC, "realloc", BT_FN_PTR_PTR_SIZE,
ATTR_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR,
ATTR_NORETURN_NOTHROW_LEAF_LIST)
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c.orig 2014-02-06 12:43:09.597012063 +0100
--- gcc/tree-ssa-structalias.c 2014-02-06 15:07:22.987416288 +0100
*************** handle_lhs_call (gimple stmt, tree lhs,
*** 3982,3988 ****
struct constraint_expr tmpc;
rhsc.create (0);
vi = make_heapvar ("HEAP");
! /* We marking allocated storage local, we deal with it becoming
global by escaping and setting of vars_contains_escaped_heap. */
DECL_EXTERNAL (vi->decl) = 0;
vi->is_global_var = 0;
--- 3982,3988 ----
struct constraint_expr tmpc;
rhsc.create (0);
vi = make_heapvar ("HEAP");
! /* We are marking allocated storage local, we deal with it becoming
global by escaping and setting of vars_contains_escaped_heap. */
DECL_EXTERNAL (vi->decl) = 0;
vi->is_global_var = 0;
*************** find_func_aliases_for_builtin_call (gimp
*** 4231,4236 ****
--- 4231,4256 ----
lhsc.release ();
return true;
}
+ case BUILT_IN_POSIX_MEMALIGN:
+ {
+ tree ptrptr = gimple_call_arg (t, 0);
+ get_constraint_for (ptrptr, &lhsc);
+ do_deref (&lhsc);
+ varinfo_t vi = make_heapvar ("HEAP");
+ /* We are marking allocated storage local, we deal with it becoming
+ global by escaping and setting of vars_contains_escaped_heap. */
+ DECL_EXTERNAL (vi->decl) = 0;
+ vi->is_global_var = 0;
+ struct constraint_expr tmpc;
+ tmpc.var = vi->id;
+ tmpc.offset = 0;
+ tmpc.type = ADDRESSOF;
+ rhsc.safe_push (tmpc);
+ process_all_all_constraints (lhsc, rhsc);
+ lhsc.release ();
+ rhsc.release ();
+ return true;
+ }
case BUILT_IN_ASSUME_ALIGNED:
{
tree res = gimple_call_lhs (t);
*************** find_func_clobbers (gimple origt)
*** 4960,4965 ****
--- 4980,4986 ----
its argument. */
case BUILT_IN_MEMSET:
case BUILT_IN_MEMSET_CHK:
+ case BUILT_IN_POSIX_MEMALIGN:
{
tree dest = gimple_call_arg (t, 0);
unsigned i;
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig 2014-02-06 12:43:09.598012063 +0100
--- gcc/tree-ssa-alias.c 2014-02-06 15:06:39.716419267 +0100
*************** ref_maybe_used_by_call_p_1 (gimple call,
*** 1515,1520 ****
--- 1515,1521 ----
/* The following builtins do not read from memory. */
case BUILT_IN_FREE:
case BUILT_IN_MALLOC:
+ case BUILT_IN_POSIX_MEMALIGN:
case BUILT_IN_CALLOC:
case BUILT_IN_ALLOCA:
case BUILT_IN_ALLOCA_WITH_ALIGN:
*************** call_may_clobber_ref_p_1 (gimple call, a
*** 1838,1843 ****
--- 1839,1854 ----
case BUILT_IN_ALLOCA_WITH_ALIGN:
case BUILT_IN_ASSUME_ALIGNED:
return false;
+ /* But posix_memalign stores a pointer into the memory pointed to
+ by its first argument. */
+ case BUILT_IN_POSIX_MEMALIGN:
+ {
+ tree ptrptr = gimple_call_arg (call, 0);
+ ao_ref dref;
+ ao_ref_init_from_ptr_and_size (&dref, ptrptr,
+ TYPE_SIZE_UNIT (ptr_type_node));
+ return refs_may_alias_p_1 (&dref, ref, false);
+ }
/* Freeing memory kills the pointed-to memory. More importantly
the call has to serve as a barrier for moving loads and stores
across it. */
Index: gcc/testsuite/gcc.dg/tree-ssa/alias-30.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/alias-30.c 2014-02-06 15:10:01.991405340
+0100
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre-details" } */
+
+ extern int posix_memalign(void **memptr,
+ __SIZE_TYPE__ alignment, __SIZE_TYPE__ size);
+
+ int foo (int *p)
+ {
+ int res = *p;
+ int *q;
+ void *tem;
+ if (posix_memalign (&tem, 128, 128 * sizeof (int)) != 0)
+ return 0;
+ q = (int *)tem;
+ *q = 1;
+ return res + *p;
+ }
+
+ /* We should be able to CSE the load from *p in the return stmt. */
+
+ /* { dg-final { scan-tree-dump "Replaced \\\*p" "fre1" } } */
+ /* { dg-final { cleanup-tree-dump "fre1" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/alias-31.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/alias-31.c 2014-02-06 15:11:55.881397499
+0100
***************
*** 0 ****
--- 1,24 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-cddce1" } */
+
+ extern int posix_memalign(void **memptr,
+ __SIZE_TYPE__ alignment, __SIZE_TYPE__ size);
+
+ int foo (int *p)
+ {
+ int res = *p;
+ struct { void *q1; void *q2; } q;
+ if (posix_memalign (&q.q1, 128, 128 * sizeof (int)) != 0)
+ return 0;
+ if (posix_memalign (&q.q2, 128, 128 * sizeof (int)) != 0)
+ return 0;
+ *((int *)q.q1) = 1;
+ *((int *)q.q2) = 2;
+ return res + *p + *((int *)q.q1) + *((int *)q.q2);
+ }
+
+ /* 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" } } */