It was noted that we now simplify pointer equality tests against restrict qualified pointers which we can't do according to reading of the fine-prints in the C standard done by Joseph.
Fixed as follows. Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2016-05-12 Richard Biener <rguent...@suse.de> PR tree-optimization/71062 * tree-ssa-alias.h (struct pt_solution): Add vars_contains_restrict field. * tree-ssa-structalias.c (set_uids_in_ptset): Set vars_contains_restrict if the var is a restrict tag. * tree-ssa-alias.c (ptrs_compare_unequal): If vars_contains_restrict do not disambiguate pointers against it. (dump_points_to_solution): Re-structure and adjust for new vars_contains_restrict flag. * gimple-pretty-print.c (pp_points_to_solution): Likewise. * gcc.dg/torture/pr71062.c: New testcase. Index: gcc/tree-ssa-alias.h =================================================================== *** gcc/tree-ssa-alias.h (revision 236159) --- gcc/tree-ssa-alias.h (working copy) *************** struct GTY(()) pt_solution *** 47,53 **** includes memory at address NULL. */ unsigned int null : 1; - /* Nonzero if the vars bitmap includes a variable included in 'nonlocal'. */ unsigned int vars_contains_nonlocal : 1; /* Nonzero if the vars bitmap includes a variable included in 'escaped'. */ --- 47,52 ---- *************** struct GTY(()) pt_solution *** 55,60 **** --- 54,62 ---- /* Nonzero if the vars bitmap includes a anonymous heap variable that escaped the function and thus became global. */ unsigned int vars_contains_escaped_heap : 1; + /* Nonzero if the vars bitmap includes a anonymous variable used to + represent storage pointed to by a restrict qualified pointer. */ + unsigned int vars_contains_restrict : 1; /* Set of variables that this pointer may point to. */ bitmap vars; Index: gcc/tree-ssa-alias.c =================================================================== *** gcc/tree-ssa-alias.c (revision 236159) --- gcc/tree-ssa-alias.c (working copy) *************** ptrs_compare_unequal (tree ptr1, tree pt *** 363,376 **** else if (obj1 && TREE_CODE (ptr2) == SSA_NAME) { struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr2); ! if (!pi) return false; return !pt_solution_includes (&pi->pt, obj1); } else if (TREE_CODE (ptr1) == SSA_NAME && obj2) { struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr1); ! if (!pi) return false; return !pt_solution_includes (&pi->pt, obj2); } --- 363,379 ---- else if (obj1 && TREE_CODE (ptr2) == SSA_NAME) { struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr2); ! /* We may not use restrict to optimize pointer comparisons. ! See PR71062. So we have to assume that restrict-pointed-to ! may be in fact obj1. */ ! if (!pi || pi->pt.vars_contains_restrict) return false; return !pt_solution_includes (&pi->pt, obj1); } else if (TREE_CODE (ptr1) == SSA_NAME && obj2) { struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr1); ! if (!pi || pi->pt.vars_contains_restrict) return false; return !pt_solution_includes (&pi->pt, obj2); } *************** dump_points_to_solution (FILE *file, str *** 521,537 **** fprintf (file, ", points-to vars: "); dump_decl_set (file, pt->vars); if (pt->vars_contains_nonlocal ! && pt->vars_contains_escaped_heap) ! fprintf (file, " (nonlocal, escaped heap)"); ! else if (pt->vars_contains_nonlocal ! && pt->vars_contains_escaped) ! fprintf (file, " (nonlocal, escaped)"); ! else if (pt->vars_contains_nonlocal) ! fprintf (file, " (nonlocal)"); ! else if (pt->vars_contains_escaped_heap) ! fprintf (file, " (escaped heap)"); ! else if (pt->vars_contains_escaped) ! fprintf (file, " (escaped)"); } } --- 524,554 ---- fprintf (file, ", points-to vars: "); dump_decl_set (file, pt->vars); if (pt->vars_contains_nonlocal ! || pt->vars_contains_escaped ! || pt->vars_contains_escaped_heap ! || pt->vars_contains_restrict) ! { ! const char *comma = ""; ! fprintf (file, " ("); ! if (pt->vars_contains_nonlocal) ! { ! fprintf (file, "nonlocal"); ! comma = ", "; ! } ! if (pt->vars_contains_escaped) ! { ! fprintf (file, "%sescaped", comma); ! comma = ", "; ! } ! if (pt->vars_contains_escaped_heap) ! { ! fprintf (file, "%sescaped heap", comma); ! comma = ", "; ! } ! if (pt->vars_contains_restrict) ! fprintf (file, "%srestrict", comma); ! fprintf (file, ")"); ! } } } Index: gcc/testsuite/gcc.dg/torture/pr71062.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr71062.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr71062.c (working copy) *************** *** 0 **** --- 1,20 ---- + /* { dg-do run } */ + + extern void abort (void); + + char bar; + + int __attribute__((noinline,noclone)) + foo (char *__restrict p) + { + if (p == &bar) + return 1; + return 0; + } + + int main() + { + if (foo (&bar) != 1) + abort (); + return 0; + } Index: gcc/gimple-pretty-print.c =================================================================== *** gcc/gimple-pretty-print.c (revision 236159) --- gcc/gimple-pretty-print.c (working copy) *************** pp_points_to_solution (pretty_printer *b *** 632,648 **** } pp_right_brace (buffer); if (pt->vars_contains_nonlocal ! && pt->vars_contains_escaped_heap) ! pp_string (buffer, " (nonlocal, escaped heap)"); ! else if (pt->vars_contains_nonlocal ! && pt->vars_contains_escaped) ! pp_string (buffer, " (nonlocal, escaped)"); ! else if (pt->vars_contains_nonlocal) ! pp_string (buffer, " (nonlocal)"); ! else if (pt->vars_contains_escaped_heap) ! pp_string (buffer, " (escaped heap)"); ! else if (pt->vars_contains_escaped) ! pp_string (buffer, " (escaped)"); } } --- 633,669 ---- } pp_right_brace (buffer); if (pt->vars_contains_nonlocal ! || pt->vars_contains_escaped ! || pt->vars_contains_escaped_heap ! || pt->vars_contains_restrict) ! { ! const char *comma = ""; ! pp_string (buffer, " ("); ! if (pt->vars_contains_nonlocal) ! { ! pp_string (buffer, "nonlocal"); ! comma = ", "; ! } ! if (pt->vars_contains_escaped) ! { ! pp_string (buffer, comma); ! pp_string (buffer, "escaped"); ! comma = ", "; ! } ! if (pt->vars_contains_escaped_heap) ! { ! pp_string (buffer, comma); ! pp_string (buffer, "escaped heap"); ! comma = ", "; ! } ! if (pt->vars_contains_restrict) ! { ! pp_string (buffer, comma); ! pp_string (buffer, "restrict"); ! } ! pp_string (buffer, ")"); ! } ! } } Index: gcc/tree-ssa-structalias.c =================================================================== *** gcc/tree-ssa-structalias.c (revision 236167) --- gcc/tree-ssa-structalias.c (working copy) *************** set_uids_in_ptset (bitmap into, bitmap f *** 6254,6259 **** --- 6254,6262 ---- pt->vars_contains_escaped_heap = vi->is_heap_var; } + if (vi->is_restrict_var) + pt->vars_contains_restrict = true; + if (TREE_CODE (vi->decl) == VAR_DECL || TREE_CODE (vi->decl) == PARM_DECL || TREE_CODE (vi->decl) == RESULT_DECL) *************** make_pass_build_ealias (gcc::context *ct *** 7505,7511 **** /* IPA PTA solutions for ESCAPED. */ struct pt_solution ipa_escaped_pt ! = { true, false, false, false, false, false, false, false, NULL }; /* Associate node with varinfo DATA. Worker for cgraph_for_symbol_thunks_and_aliases. */ --- 7508,7514 ---- /* IPA PTA solutions for ESCAPED. */ struct pt_solution ipa_escaped_pt ! = { true, false, false, false, false, false, false, false, false, NULL }; /* Associate node with varinfo DATA. Worker for cgraph_for_symbol_thunks_and_aliases. */