https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117432
Richard Sandiford <rsandifo at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rsandifo at gcc dot gnu.org --- Comment #9 from Richard Sandiford <rsandifo at gcc dot gnu.org> --- (In reply to Jan Hubicka from comment #7) > Hash needs to be stable for LTO streaming which affects types. But at least > we ought to compare types when we are comparing bodies in > func_checker::compare_gimple_call. I guess for non-varadic calls this > happens since both calls must have same signature. > > This untested patch may fix it > diff --git a/gcc/ipa-icf-gimple.cc b/gcc/ipa-icf-gimple.cc > index 31f6cdbda06..ef9e3ea3164 100644 > --- a/gcc/ipa-icf-gimple.cc > +++ b/gcc/ipa-icf-gimple.cc > @@ -746,6 +746,8 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2) > > if (!compare_operand (t1, t2, get_operand_access_type (&map, t1))) > return return_false_with_msg ("GIMPLE call operands are different"); > + if (!types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)) > + return return_false_with_msg ("GIMPLE call operand types are > different"); > } > > /* Return value checking. */ > > I wonder if it won't cause us to give up too often, perhaps we could do that > only for variadic calls and calls with no prototype or so. What about Alexander's asm example in comment 6? I just hit what looks like another instance of this when trying to write a testcase for a different bug: void f1 () { struct { unsigned short a, b; } x; unsigned int y; asm ("" : "=r" (x), "=r" (y)); x.a = y; asm volatile ("" :: "r" (x)); } void f2 () { struct { unsigned short a, b; } x; unsigned char y; asm ("" : "=r" (x), "=r" (y)); x.a = y; asm volatile ("" :: "r" (x)); } icf treats f2 as a dup of f1, even though f2 includes a zero extension from unsigned char to unsigned short. Thus on aarch64 we get: f1: bfi w0, w1, 0, 16 ret f2: bfi w0, w1, 0, 16 ret