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