summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-06-21 06:59:33 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-06-21 06:59:33 +0000
commitec15ec364cc3422cb5960abe812c4df3d8f9128c (patch)
treee44c3058192b42758cc768621ec38577922dc5f1
parentfaeffe493be6fb9c3ab298ec88a15844d4089b84 (diff)
downloadgcc-ec15ec364cc3422cb5960abe812c4df3d8f9128c.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@237628 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr71558.c17
-rw-r--r--gcc/tree-ssa-strlen.c66
4 files changed, 92 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1f47a9d9bef..14b8030ec69 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2016-06-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/71588
+ * tree-ssa-strlen.c (valid_builtin_call): New function.
+ (adjust_last_stmt, handle_builtin_memset, strlen_optimize_stmt): Use
+ it.
+
2016-06-20 Jakub Jelinek <jakub@redhat.com>
PR middle-end/71581
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a968cd41456..0f6fe946732 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-06-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/71588
+ * gcc.dg/pr71558.c: New test.
+
2016-06-21 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
* c-c++-common/pr68657-1.c: Require ptr32plus support.
diff --git a/gcc/testsuite/gcc.dg/pr71558.c b/gcc/testsuite/gcc.dg/pr71558.c
new file mode 100644
index 00000000000..33a648e108c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr71558.c
@@ -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);
+}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 700d6ce2bdb..f306a9c9f3d 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -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 *stmt, bool is_strcat)
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_iterator *gsi)
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_iterator *gsi)
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: