From 0ad84f34fc91885b187c302c8abf1dd6bae4a671 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 21 Jun 2016 08:59:33 +0200 Subject: [PATCH] re PR tree-optimization/71588 (ICE on valid code at -O2 and -O3 on x86_64-linux-gnu: in execute_todo, at passes.c:2009) 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. From-SVN: r237628 --- gcc/ChangeLog | 7 ++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/pr71558.c | 17 +++++++++ gcc/tree-ssa-strlen.c | 66 ++++++++++++++++++++++++++++++++-- 4 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr71558.c 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 + + 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 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 + + PR tree-optimization/71588 + * gcc.dg/pr71558.c: New test. + 2016-06-21 Senthil Kumar Selvaraj * 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: -- 2.30.2