diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-06-21 06:59:33 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-06-21 06:59:33 +0000 |
commit | ec15ec364cc3422cb5960abe812c4df3d8f9128c (patch) | |
tree | e44c3058192b42758cc768621ec38577922dc5f1 | |
parent | faeffe493be6fb9c3ab298ec88a15844d4089b84 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr71558.c | 17 | ||||
-rw-r--r-- | gcc/tree-ssa-strlen.c | 66 |
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: |