This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR59630
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 7 Jan 2014 15:57:52 +0100 (CET)
- Subject: [PATCH] Fix PR59630
- Authentication-results: sourceware.org; auth=none
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 <rguenther@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);
+ }