diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6b7ef3eb04b..7fb1b33462c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2013-01-07 Richard Biener + + PR middle-end/55890 + * gimple.h (gimple_call_builtin_p): New overload. + * gimple.c (validate_call): New function. + (gimple_call_builtin_p): Likewise. + * tree-ssa-structalias.c (find_func_aliases_for_builtin_call): + Use gimple_call_builtin_p. + (find_func_clobbers): Likewise. + * tree-ssa-strlen.c (adjust_last_stmt): Likewise. + (strlen_optimize_stmt): Likewise. + 2013-01-07 James Greenhalgh * config/aarch64/arm_neon.h (vld1_dup_*): Make argument const. diff --git a/gcc/gimple.c b/gcc/gimple.c index 5a53e0082c0..4f4bac860c4 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -4137,16 +4137,60 @@ is_gimple_builtin_call (gimple stmt) return false; } -/* Return true when STMT is builtins call to CODE. */ +/* Return true when STMTs arguments match those of FNDECL. */ + +static bool +validate_call (gimple stmt, tree fndecl) +{ + tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + unsigned nargs = gimple_call_num_args (stmt); + for (unsigned i = 0; i < nargs; ++i) + { + /* Variadic args follow. */ + if (!targs) + return true; + tree arg = gimple_call_arg (stmt, i); + if (INTEGRAL_TYPE_P (TREE_TYPE (arg)) + && INTEGRAL_TYPE_P (TREE_VALUE (targs))) + ; + else if (POINTER_TYPE_P (TREE_TYPE (arg)) + && POINTER_TYPE_P (TREE_VALUE (targs))) + ; + else if (TREE_CODE (TREE_TYPE (arg)) + != TREE_CODE (TREE_VALUE (targs))) + return false; + targs = TREE_CHAIN (targs); + } + if (targs && !VOID_TYPE_P (TREE_VALUE (targs))) + return false; + return true; +} + +/* Return true when STMT is builtins call to CLASS. */ + +bool +gimple_call_builtin_p (gimple stmt, enum built_in_class klass) +{ + tree fndecl; + if (is_gimple_call (stmt) + && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE + && DECL_BUILT_IN_CLASS (fndecl) == klass) + return validate_call (stmt, fndecl); + return false; +} + +/* Return true when STMT is builtins call to CODE of CLASS. */ bool gimple_call_builtin_p (gimple stmt, enum built_in_function code) { tree fndecl; - return (is_gimple_call (stmt) - && (fndecl = gimple_call_fndecl (stmt)) != NULL - && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL - && DECL_FUNCTION_CODE (fndecl) == code); + if (is_gimple_call (stmt) + && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (fndecl) == code) + return validate_call (stmt, fndecl); + return false; } /* Return true if STMT clobbers memory. STMT is required to be a diff --git a/gcc/gimple.h b/gcc/gimple.h index 5fcaac60d08..a5be00a48aa 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -893,6 +893,7 @@ extern bool walk_stmt_load_store_ops (gimple, void *, bool (*)(gimple, tree, void *), bool (*)(gimple, tree, void *)); extern bool gimple_ior_addresses_taken (bitmap, gimple); +extern bool gimple_call_builtin_p (gimple, enum built_in_class); extern bool gimple_call_builtin_p (gimple, enum built_in_function); extern bool gimple_asm_clobbers_memory_p (const_gimple); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 178459ea04e..80f18baf19b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-01-07 Richard Biener + + PR middle-end/55890 + * gcc.dg/torture/pr55890-1.c: New testcase. + * gcc.dg/torture/pr55890-2.c: Likewise. + 2013-01-07 James Greenhalgh * gcc.target/aarch64/fmovd.c: New. diff --git a/gcc/testsuite/gcc.dg/torture/pr55890-1.c b/gcc/testsuite/gcc.dg/torture/pr55890-1.c new file mode 100644 index 00000000000..9fd558ea03f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr55890-1.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ + +extern void *memmove(void *, void *, __SIZE_TYPE__); +typedef int (*_TEST_fun_) (); +static _TEST_fun_ i = (_TEST_fun_) memmove; +main() { i(); } diff --git a/gcc/testsuite/gcc.dg/torture/pr55890-2.c b/gcc/testsuite/gcc.dg/torture/pr55890-2.c new file mode 100644 index 00000000000..a753e573dce --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr55890-2.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ + +extern void *memcpy(); +main() { memcpy(); } diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index aa8b3d69164..a574a83fe43 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -807,12 +807,10 @@ adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat) return; } - if (!is_gimple_call (last.stmt)) - return; - callee = gimple_call_fndecl (last.stmt); - if (callee == NULL_TREE || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL) + if (!gimple_call_builtin_p (last.stmt, BUILT_IN_NORMAL)) return; + callee = gimple_call_fndecl (last.stmt); switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_MEMCPY: @@ -1750,7 +1748,7 @@ strlen_optimize_stmt (gimple_stmt_iterator *gsi) if (is_gimple_call (stmt)) { tree callee = gimple_call_fndecl (stmt); - if (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) + if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_STRLEN: diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 4c3cb329624..8eb8544a3d4 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -4014,8 +4014,7 @@ find_func_aliases_for_builtin_call (gimple t) vec rhsc = vNULL; varinfo_t fi; - if (fndecl != NULL_TREE - && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) + if (gimple_call_builtin_p (t, BUILT_IN_NORMAL)) /* ??? All builtins that are handled here need to be handled in the alias-oracle query functions explicitly! */ switch (DECL_FUNCTION_CODE (fndecl)) @@ -4768,8 +4767,7 @@ find_func_clobbers (gimple origt) /* For builtins we do not have separate function info. For those we do not generate escapes for we have to generate clobbers/uses. */ - if (decl - && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) + if (gimple_call_builtin_p (t, BUILT_IN_NORMAL)) switch (DECL_FUNCTION_CODE (decl)) { /* The following functions use and clobber memory pointed to