Re: [PATCH] Give up instead of ICE on invalid stringops attributes (PR tree-optimization/71588)

2016-06-20 Thread Jeff Law

On 06/20/2016 12:35 PM, Jakub Jelinek wrote:

Hi!

If users use attributes like const or pure incorrectly on stringops
builtins, the tree-ssa-strlen.c pass can ICE, because it expects it can e.g.
replace a strcpy (which should not be const or pure) with memcpy (which also
shouldn't be const/pure) etc.
The patch just pretends the calls aren't builtins for the purpose of
tree-ssa-strlen.c pass if they have unexpected const/pure-ness.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/6.2?

2016-06-20  Jakub Jelinek  

PR tree-optimization/71588
* tree-ssa-strlen.c (valid_builtin_call): New function.
(adjust_last_stmt, handle_builtin_memset, strlen_optimize_stmt): Use
it.

* gcc.dg/pr71558.c: New test.

OK.
jeff






[PATCH] Give up instead of ICE on invalid stringops attributes (PR tree-optimization/71588)

2016-06-20 Thread Jakub Jelinek
Hi!

If users use attributes like const or pure incorrectly on stringops
builtins, the tree-ssa-strlen.c pass can ICE, because it expects it can e.g.
replace a strcpy (which should not be const or pure) with memcpy (which also
shouldn't be const/pure) etc.
The patch just pretends the calls aren't builtins for the purpose of
tree-ssa-strlen.c pass if they have unexpected const/pure-ness.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/6.2?

2016-06-20  Jakub Jelinek  

PR tree-optimization/71588
* tree-ssa-strlen.c (valid_builtin_call): New function.
(adjust_last_stmt, handle_builtin_memset, strlen_optimize_stmt): Use
it.

* gcc.dg/pr71558.c: New test.

--- gcc/tree-ssa-strlen.c.jj2016-06-08 14:51:25.0 +0200
+++ gcc/tree-ssa-strlen.c   2016-06-20 13:30:23.576556803 +0200
@@ -860,6 +860,66 @@ find_equal_ptrs (tree ptr, int idx)
 }
 }
 
+/* Return true if STMT is a call to a builtin function with the right
+   arguments and attributes that should be considered for optimization
+   by this pass.  */
+
+static bool
+valid_builtin_call (gimple *stmt)
+{
+  if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+return false;
+
+  tree callee = gimple_call_fndecl (stmt);
+  switch (DECL_FUNCTION_CODE (callee))
+{
+case BUILT_IN_MEMCMP:
+case BUILT_IN_MEMCMP_EQ:
+case BUILT_IN_STRCHR:
+case BUILT_IN_STRCHR_CHKP:
+case BUILT_IN_STRLEN:
+case BUILT_IN_STRLEN_CHKP:
+  /* The above functions should be pure.  Punt if they aren't.  */
+  if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE)
+   return false;
+  break;
+
+case BUILT_IN_CALLOC:
+case BUILT_IN_MALLOC:
+case BUILT_IN_MEMCPY:
+case BUILT_IN_MEMCPY_CHK:
+case BUILT_IN_MEMCPY_CHKP:
+case BUILT_IN_MEMCPY_CHK_CHKP:
+case BUILT_IN_MEMPCPY:
+case BUILT_IN_MEMPCPY_CHK:
+case BUILT_IN_MEMPCPY_CHKP:
+case BUILT_IN_MEMPCPY_CHK_CHKP:
+case BUILT_IN_MEMSET:
+case BUILT_IN_STPCPY:
+case BUILT_IN_STPCPY_CHK:
+case BUILT_IN_STPCPY_CHKP:
+case BUILT_IN_STPCPY_CHK_CHKP:
+case BUILT_IN_STRCAT:
+case BUILT_IN_STRCAT_CHK:
+case BUILT_IN_STRCAT_CHKP:
+case BUILT_IN_STRCAT_CHK_CHKP:
+case BUILT_IN_STRCPY:
+case BUILT_IN_STRCPY_CHK:
+case BUILT_IN_STRCPY_CHKP:
+case BUILT_IN_STRCPY_CHK_CHKP:
+  /* The above functions should be neither const nor pure.  Punt if they
+aren't.  */
+  if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE)
+   return false;
+  break;
+
+default:
+  break;
+}
+
+  return true;
+}
+
 /* If the last .MEM setter statement before STMT is
memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT
and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to
@@ -935,7 +995,7 @@ adjust_last_stmt (strinfo *si, gimple *s
   return;
 }
 
-  if (!gimple_call_builtin_p (last.stmt, BUILT_IN_NORMAL))
+  if (!valid_builtin_call (last.stmt))
 return;
 
   callee = gimple_call_fndecl (last.stmt);
@@ -1811,7 +1871,7 @@ handle_builtin_memset (gimple_stmt_itera
   if (!stmt1 || !is_gimple_call (stmt1))
 return true;
   tree callee1 = gimple_call_fndecl (stmt1);
-  if (!gimple_call_builtin_p (stmt1, BUILT_IN_NORMAL))
+  if (!valid_builtin_call (stmt1))
 return true;
   enum built_in_function code1 = DECL_FUNCTION_CODE (callee1);
   tree size = gimple_call_arg (stmt2, 2);
@@ -2140,7 +2200,7 @@ strlen_optimize_stmt (gimple_stmt_iterat
   if (is_gimple_call (stmt))
 {
   tree callee = gimple_call_fndecl (stmt);
-  if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+  if (valid_builtin_call (stmt))
switch (DECL_FUNCTION_CODE (callee))
  {
  case BUILT_IN_STRLEN:
--- gcc/testsuite/gcc.dg/pr71558.c.jj   2016-06-20 13:52:15.491591442 +0200
+++ gcc/testsuite/gcc.dg/pr71558.c  2016-06-20 13:51:59.0 +0200
@@ -0,0 +1,17 @@
+/* PR tree-optimization/71588 */
+
+/* strcpy must not be pure, but make sure we don't ICE even when
+   it is declared incorrectly.  */
+char *strcpy (char *, const char *) __attribute__ ((__pure__));
+__SIZE_TYPE__ strlen (const char *);
+void *malloc (__SIZE_TYPE__);
+
+char a[20];
+
+char *
+foo (void)
+{
+  __SIZE_TYPE__ b = strlen (a);
+  char *c = malloc (b);
+  return strcpy (c, a);
+}

Jakub