This fixes the testcase in PR59630 by properly using (and extending) the predicates we have to check for builtin calls.
Boostrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2014-01-07 Richard Biener <rguent...@suse.de> PR middle-end/59630 * gimple.h (is_gimple_builtin_call): Remove. (gimple_builtin_call_types_compatible_p): New. (gimple_call_builtin_p): New overload. * gimple.c (is_gimple_builtin_call): Remove. (validate_call): Rename to ... (gimple_builtin_call_types_compatible_p): ... this and export. Also check return types. (validate_type): New static function. (gimple_call_builtin_p): New overload and adjust. * gimple-fold.c (gimple_fold_builtin): Fold the return value. (gimple_fold_call): Likewise. Use gimple_call_builtin_p. (gimple_fold_stmt_to_constant_1): Likewise. * tsan.c (instrument_gimple): Use gimple_call_builtin_p. * gcc.dg/pr59630.c: New testcase. Index: gcc/gimple.h =================================================================== *** gcc/gimple.h (revision 206385) --- gcc/gimple.h (working copy) *************** extern tree gimple_unsigned_type (tree); *** 1253,1259 **** extern tree gimple_signed_type (tree); extern alias_set_type gimple_get_alias_set (tree); extern bool gimple_ior_addresses_taken (bitmap, gimple); ! extern bool is_gimple_builtin_call (gimple stmt); 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); --- 1253,1260 ---- extern tree gimple_signed_type (tree); extern alias_set_type gimple_get_alias_set (tree); extern bool gimple_ior_addresses_taken (bitmap, gimple); ! extern bool gimple_builtin_call_types_compatible_p (gimple, tree); ! extern bool gimple_call_builtin_p (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); Index: gcc/gimple.c =================================================================== *** gcc/gimple.c (revision 206385) --- gcc/gimple.c (working copy) *************** gimple_ior_addresses_taken (bitmap addre *** 2351,2377 **** } ! /* Return TRUE iff stmt is a call to a built-in function. */ ! bool ! is_gimple_builtin_call (gimple stmt) { ! tree callee; ! ! if (is_gimple_call (stmt) ! && (callee = gimple_call_fndecl (stmt)) ! && is_builtin_fn (callee) ! && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) ! return true; ! ! return false; } ! /* 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) --- 2351,2387 ---- } ! /* Return true if TYPE1 and TYPE2 are compatible enough for builtin ! processing. */ ! static bool ! validate_type (tree type1, tree type2) { ! if (INTEGRAL_TYPE_P (type1) ! && INTEGRAL_TYPE_P (type2)) ! ; ! else if (POINTER_TYPE_P (type1) ! && POINTER_TYPE_P (type2)) ! ; ! else if (TREE_CODE (type1) ! != TREE_CODE (type2)) ! return false; ! return true; } ! /* Return true when STMTs arguments and return value match those of FNDECL, ! a decl of a builtin function. */ ! bool ! gimple_builtin_call_types_compatible_p (gimple stmt, tree fndecl) { + gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN); + + tree ret = gimple_call_lhs (stmt); + if (ret + && !validate_type (TREE_TYPE (ret), TREE_TYPE (TREE_TYPE (fndecl)))) + return false; + tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); unsigned nargs = gimple_call_num_args (stmt); for (unsigned i = 0; i < nargs; ++i) *************** validate_call (gimple stmt, tree fndecl) *** 2380,2393 **** 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); } --- 2390,2396 ---- if (!targs) return true; tree arg = gimple_call_arg (stmt, i); ! if (!validate_type (TREE_TYPE (arg), TREE_VALUE (targs))) return false; targs = TREE_CHAIN (targs); } *************** validate_call (gimple stmt, tree fndecl) *** 2396,2401 **** --- 2399,2417 ---- return true; } + /* Return true when STMT is builtins call. */ + + bool + gimple_call_builtin_p (gimple stmt) + { + tree fndecl; + if (is_gimple_call (stmt) + && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE + && DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN) + return gimple_builtin_call_types_compatible_p (stmt, fndecl); + return false; + } + /* Return true when STMT is builtins call to CLASS. */ bool *************** gimple_call_builtin_p (gimple stmt, enum *** 2405,2411 **** 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; } --- 2421,2427 ---- if (is_gimple_call (stmt) && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE && DECL_BUILT_IN_CLASS (fndecl) == klass) ! return gimple_builtin_call_types_compatible_p (stmt, fndecl); return false; } *************** gimple_call_builtin_p (gimple stmt, enum *** 2419,2425 **** && (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; } --- 2435,2441 ---- && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (fndecl) == code) ! return gimple_builtin_call_types_compatible_p (stmt, fndecl); return false; } Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c (revision 206385) --- gcc/gimple-fold.c (working copy) *************** gimple_fold_builtin (gimple stmt) *** 879,886 **** int nargs; location_t loc = gimple_location (stmt); - gcc_assert (is_gimple_call (stmt)); - ignore = (gimple_call_lhs (stmt) == NULL); /* First try the generic builtin folder. If that succeeds, return the --- 879,884 ---- *************** gimple_fold_builtin (gimple stmt) *** 890,895 **** --- 888,895 ---- { if (ignore) STRIP_NOPS (result); + else + result = fold_convert (gimple_call_return_type (stmt), result); return result; } *************** gimple_fold_call (gimple_stmt_iterator * *** 1206,1213 **** /* Check for builtins that CCP can handle using information not available in the generic fold routines. */ ! callee = gimple_call_fndecl (stmt); ! if (callee && DECL_BUILT_IN (callee)) { tree result = gimple_fold_builtin (stmt); if (result) --- 1206,1212 ---- /* Check for builtins that CCP can handle using information not available in the generic fold routines. */ ! if (gimple_call_builtin_p (stmt)) { tree result = gimple_fold_builtin (stmt); if (result) *************** gimple_fold_call (gimple_stmt_iterator * *** 1216,1222 **** gimplify_and_update_call_from_tree (gsi, result); changed = true; } ! else if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD) changed |= targetm.gimple_fold_builtin (gsi); } --- 1215,1221 ---- gimplify_and_update_call_from_tree (gsi, result); changed = true; } ! else if (gimple_call_builtin_p (stmt, BUILT_IN_MD)) changed |= targetm.gimple_fold_builtin (gsi); } *************** gimple_fold_stmt_to_constant_1 (gimple s *** 2726,2732 **** fn = (*valueize) (gimple_call_fn (stmt)); if (TREE_CODE (fn) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL ! && DECL_BUILT_IN (TREE_OPERAND (fn, 0))) { tree *args = XALLOCAVEC (tree, gimple_call_num_args (stmt)); tree call, retval; --- 2725,2733 ---- fn = (*valueize) (gimple_call_fn (stmt)); if (TREE_CODE (fn) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL ! && DECL_BUILT_IN (TREE_OPERAND (fn, 0)) ! && gimple_builtin_call_types_compatible_p (stmt, ! TREE_OPERAND (fn, 0))) { tree *args = XALLOCAVEC (tree, gimple_call_num_args (stmt)); tree call, retval; *************** gimple_fold_stmt_to_constant_1 (gimple s *** 2738,2745 **** fn, gimple_call_num_args (stmt), args); retval = fold_call_expr (EXPR_LOCATION (call), call, false); if (retval) ! /* fold_call_expr wraps the result inside a NOP_EXPR. */ ! STRIP_NOPS (retval); return retval; } return NULL_TREE; --- 2739,2749 ---- fn, gimple_call_num_args (stmt), args); retval = fold_call_expr (EXPR_LOCATION (call), call, false); if (retval) ! { ! /* fold_call_expr wraps the result inside a NOP_EXPR. */ ! STRIP_NOPS (retval); ! retval = fold_convert (gimple_call_return_type (stmt), retval); ! } return retval; } return NULL_TREE; Index: gcc/tsan.c =================================================================== *** gcc/tsan.c (revision 206385) --- gcc/tsan.c (working copy) *************** instrument_gimple (gimple_stmt_iterator *** 609,615 **** && (gimple_call_fndecl (stmt) != builtin_decl_implicit (BUILT_IN_TSAN_INIT))) { ! if (is_gimple_builtin_call (stmt)) instrument_builtin_call (gsi); return true; } --- 609,615 ---- && (gimple_call_fndecl (stmt) != builtin_decl_implicit (BUILT_IN_TSAN_INIT))) { ! if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) instrument_builtin_call (gsi); return true; } Index: gcc/testsuite/gcc.dg/pr59630.c =================================================================== *** gcc/testsuite/gcc.dg/pr59630.c (revision 0) --- gcc/testsuite/gcc.dg/pr59630.c (working copy) *************** *** 0 **** --- 1,8 ---- + /* { dg-do compile } */ + /* { dg-options "-O" } */ + + _Bool foo() + { + _Bool (*f)(int) = __builtin_abs; /* { dg-warning "" } */ + return f(0); + }