2016-07-07 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
+ 2016-06-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/71588
+ * tree-ssa-strlen.c (valid_builtin_call): New function.
+ (adjust_last_stmt, strlen_optimize_stmt): Use it.
+
2016-06-10 Jakub Jelinek <jakub@redhat.com>
PR middle-end/71494
--- /dev/null
+/* 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);
+}
}
}
+/* 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_STRCHR:
+ case BUILT_IN_STRLEN:
+ /* 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_MEMCPY:
+ case BUILT_IN_MEMCPY_CHK:
+ case BUILT_IN_MEMPCPY:
+ case BUILT_IN_MEMPCPY_CHK:
+ case BUILT_IN_STPCPY:
+ case BUILT_IN_STPCPY_CHK:
+ case BUILT_IN_STRCAT:
+ case BUILT_IN_STRCAT_CHK:
+ case BUILT_IN_STRCPY:
+ case BUILT_IN_STRCPY_CHK:
+ /* 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
return;
}
- if (!gimple_call_builtin_p (last.stmt, BUILT_IN_NORMAL))
+ if (!valid_builtin_call (last.stmt))
return;
callee = gimple_call_fndecl (last.stmt);
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: