On Fri, 31 Jan 2025, Jakub Jelinek wrote: > On Fri, Jan 31, 2025 at 02:29:57PM +0100, Jakub Jelinek wrote: > > > } > > > else > > > { > > > tree fntype1 = gimple_call_fntype (s1); > > > tree fntype2 = gimple_call_fntype (s2); > > > > > > if ((fntype1 && !fntype2) > > > || (!fntype1 && fntype2) > > > || (fntype1 && !types_compatible_p (fntype1, fntype2))) > > > return return_false_with_msg ("call function types are not > > > compatible"); > > > } > > > > > > I think in the else { fntype1 and fntype2 should never be NULL and thus > > > this should simplify even more. > > > > This isn't possible because fntype{1,2} are used later on in the function; > > sure, that > > if (fntype1 && fntype2 && comp_type_attributes (fntype1, fntype2) != 1) > > return return_false_with_msg ("different fntype attributes"); > > can be moved into the else, but the new checks to determine which args to > > check still use that. > > So like this then (if it passes bootstrap/regtest)?
LGTM. Richard. > 2025-01-31 Jakub Jelinek <ja...@redhat.com> > > PR ipa/117432 > * ipa-icf-gimple.cc (func_checker::compare_asm_inputs_outputs): > Also return_false if operands have incompatible types. > (func_checker::compare_gimple_call): Check fntype1 vs. fntype2 > compatibility for all non-internal calls and assume fntype1 and > fntype2 are non-NULL for those. For calls to non-prototyped > calls or for stdarg_p functions after the last named argument (if any) > check type compatibility of call arguments. > > * gcc.c-torture/execute/pr117432.c: New test. > * gcc.target/i386/pr117432.c: New test. > > --- gcc/ipa-icf-gimple.cc.jj 2025-01-30 18:29:22.237190471 +0100 > +++ gcc/ipa-icf-gimple.cc 2025-01-31 15:25:57.168535197 +0100 > @@ -459,7 +459,9 @@ func_checker::compare_asm_inputs_outputs > return false; > > if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2), > - get_operand_access_type (map, t1))) > + get_operand_access_type (map, t1)) > + || !types_compatible_p (TREE_TYPE (TREE_VALUE (t1)), > + TREE_TYPE (TREE_VALUE (t2)))) > return return_false (); > > tree p1 = TREE_PURPOSE (t1); > @@ -709,26 +711,37 @@ func_checker::compare_gimple_call (gcall > || gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p > (s2)) > return false; > > - if (gimple_call_internal_p (s1) > - && gimple_call_internal_fn (s1) != gimple_call_internal_fn (s2)) > - return false; > - > - tree fntype1 = gimple_call_fntype (s1); > - tree fntype2 = gimple_call_fntype (s2); > - > - /* For direct calls we verify that types are compatible so if we matched > - callees, callers must match, too. For indirect calls however verify > - function type. */ > - if (!gimple_call_fndecl (s1)) > + unsigned check_arg_types_from = 0; > + if (gimple_call_internal_p (s1)) > { > - if ((fntype1 && !fntype2) > - || (!fntype1 && fntype2) > - || (fntype1 && !types_compatible_p (fntype1, fntype2))) > - return return_false_with_msg ("call function types are not compatible"); > + if (gimple_call_internal_fn (s1) != gimple_call_internal_fn (s2)) > + return false; > } > + else > + { > + tree fntype1 = gimple_call_fntype (s1); > + tree fntype2 = gimple_call_fntype (s2); > + if (!types_compatible_p (fntype1, fntype2)) > + return return_false_with_msg ("call function types are not compatible"); > + > + if (comp_type_attributes (fntype1, fntype2) != 1) > + return return_false_with_msg ("different fntype attributes"); > > - if (fntype1 && fntype2 && comp_type_attributes (fntype1, fntype2) != 1) > - return return_false_with_msg ("different fntype attributes"); > + check_arg_types_from = gimple_call_num_args (s1); > + if (!prototype_p (fntype1) || !prototype_p (fntype2)) > + check_arg_types_from = 0; > + else if (stdarg_p (fntype1)) > + { > + check_arg_types_from = list_length (TYPE_ARG_TYPES (fntype1)); > + if (stdarg_p (fntype2)) > + { > + unsigned n = list_length (TYPE_ARG_TYPES (fntype2)); > + check_arg_types_from = MIN (check_arg_types_from, n); > + } > + } > + else if (stdarg_p (fntype2)) > + check_arg_types_from = list_length (TYPE_ARG_TYPES (fntype2)); > + } > > tree chain1 = gimple_call_chain (s1); > tree chain2 = gimple_call_chain (s2); > @@ -746,6 +759,10 @@ func_checker::compare_gimple_call (gcall > > if (!compare_operand (t1, t2, get_operand_access_type (&map, t1))) > return return_false_with_msg ("GIMPLE call operands are different"); > + if (i >= check_arg_types_from > + && !types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) > + return return_false_with_msg ("GIMPLE call operand types are " > + "different"); > } > > /* Return value checking. */ > --- gcc/testsuite/gcc.c-torture/execute/pr117432.c.jj 2025-01-31 > 15:14:54.358852495 +0100 > +++ gcc/testsuite/gcc.c-torture/execute/pr117432.c 2025-01-31 > 15:14:54.358852495 +0100 > @@ -0,0 +1,71 @@ > +/* PR ipa/117432 */ > + > +#include <stdarg.h> > + > +long long r; > + > +__attribute__((noipa)) void > +baz (int tag, ...) > +{ > + va_list ap; > + va_start (ap, tag); > + if (!r) > + r = va_arg (ap, long long); > + else > + r = va_arg (ap, int); > + va_end (ap); > +} > + > +void > +foo (void) > +{ > + baz (1, -1, 0); > +} > + > +void > +bar (void) > +{ > + baz (1, -1LL, 0); > +} > + > +__attribute__((noipa)) void > +qux (...) > +{ > + va_list ap; > + va_start (ap); > + if (!r) > + r = va_arg (ap, long long); > + else > + r = va_arg (ap, int); > + va_end (ap); > +} > + > +void > +corge (void) > +{ > + qux (-2, 0); > +} > + > +void > +fred (void) > +{ > + qux (-2LL, 0); > +} > + > +int > +main () > +{ > + bar (); > + if (r != -1LL) > + __builtin_abort (); > + foo (); > + if (r != -1) > + __builtin_abort (); > + r = 0; > + fred (); > + if (r != -2LL) > + __builtin_abort (); > + corge (); > + if (r != -2) > + __builtin_abort (); > +} > --- gcc/testsuite/gcc.target/i386/pr117432.c.jj 2025-01-31 > 15:14:54.358852495 +0100 > +++ gcc/testsuite/gcc.target/i386/pr117432.c 2025-01-31 15:14:54.358852495 > +0100 > @@ -0,0 +1,17 @@ > +/* PR ipa/117432 */ > +/* { dg-do compile { target lp64 } } */ > +/* { dg-options "-O2" } */ > +/* { dg-final { scan-assembler "# myinsn %rax" } } */ > +/* { dg-final { scan-assembler "# myinsn %eax" } } */ > + > +void > +foo (void) > +{ > + asm volatile ("# myinsn %0" : : "r" (-42L)); > +} > + > +void > +bar (void) > +{ > + asm volatile ("# myinsn %0" : : "r" (-42)); > +} > > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)