Hi! As discussed in the PR and on IRC, some places in gimple-fold.c/match.pd rely on the fact that if gimple_builtin_call_types_compatible_p succeeds, then it should be ok to pass arguments and read lhs without type conversions. But, currently this function uses validate_type, which is a very weak type compatibility check.
This patch instead requires standard middle-end type compatibility. Bootstrap/regtest of the gimple.c portion of the patch revealed a bug in value-prof.c, which has been passing constant last argument to various stringop functions in incompatible type to what the builtin wants, so I've fixed that too. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-01-13 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/69156 * gimple.c (validate_type): Removed. (gimple_builtin_call_types_compatible_p): Use useless_type_conversion_p instead of validate_type. * value-prof.c (gimple_stringop_fixed_value): Fold icall_size to correct type. * gcc.dg/pr69156.c: New test. --- gcc/gimple.c.jj 2016-01-04 14:55:53.000000000 +0100 +++ gcc/gimple.c 2016-01-13 13:15:07.194943810 +0100 @@ -2445,24 +2445,6 @@ gimple_ior_addresses_taken (bitmap addre } -/* 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. */ @@ -2473,7 +2455,8 @@ gimple_builtin_call_types_compatible_p ( tree ret = gimple_call_lhs (stmt); if (ret - && !validate_type (TREE_TYPE (ret), TREE_TYPE (TREE_TYPE (fndecl)))) + && !useless_type_conversion_p (TREE_TYPE (ret), + TREE_TYPE (TREE_TYPE (fndecl)))) return false; tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); @@ -2484,7 +2467,7 @@ gimple_builtin_call_types_compatible_p ( if (!targs) return true; tree arg = gimple_call_arg (stmt, i); - if (!validate_type (TREE_TYPE (arg), TREE_VALUE (targs))) + if (!useless_type_conversion_p (TREE_VALUE (targs), TREE_TYPE (arg))) return false; targs = TREE_CHAIN (targs); } --- gcc/value-prof.c.jj 2016-01-04 14:55:53.000000000 +0100 +++ gcc/value-prof.c 2016-01-13 13:14:56.139094912 +0100 @@ -1697,7 +1697,8 @@ gimple_stringop_fixed_value (gcall *vcal gimple_set_vuse (vcall_stmt, NULL); update_stmt (vcall_stmt); icall_stmt = as_a <gcall *> (gimple_copy (vcall_stmt)); - gimple_call_set_arg (icall_stmt, size_arg, icall_size); + gimple_call_set_arg (icall_stmt, size_arg, + fold_convert (optype, icall_size)); gsi_insert_before (&gsi, icall_stmt, GSI_SAME_STMT); /* Fix CFG. */ --- gcc/testsuite/gcc.dg/pr69156.c.jj 2016-01-13 10:42:50.465247811 +0100 +++ gcc/testsuite/gcc.dg/pr69156.c 2016-01-13 10:42:50.465247811 +0100 @@ -0,0 +1,10 @@ +/* PR tree-optimization/69156 */ +/* { dg-do compile } */ +/* { dg-options "-O1 -fno-tree-ccp" } */ + +_Bool +foo () +{ + _Bool (*f) () = __builtin_abs; /* { dg-warning "initialization from incompatible pointer type" } */ + return f (0); +} Jakub