This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [cft] Fix pr42269 -- loss of incoming promotions in combine
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>, richard dot earnshaw at arm dot com, mattst88 at gmail dot com, kkojima at gcc dot gnu dot org
- Date: Sat, 05 Dec 2009 11:58:07 +0000
- Subject: Re: [cft] Fix pr42269 -- loss of incoming promotions in combine
- References: <4B18647C.3030609@redhat.com>
Richard Henderson <rth@redhat.com> writes:
> As best I can tell, the extra sign extension seen in this pr is caused
> by the patch in
>
> http://gcc.gnu.org/ml/gcc-patches/2007-09/msg01534.html
>
> The problem is the brushed-over mention of "if the signedness matches",
> and the addition of the test "uns1 == uns3", a condition that did not
> exist before the patch. As far as I can tell, it isn't necessary.
>
> On Alpha (and at least arm, mips, sh), ABI mandated promotions may not
> match the sign of the real argument. Which, for the purposes here in
> combine, is perfectly fine. We can record that an incoming register is
> sign/zero extended from SI to DImode without regard to the source-level
> sign of the SImode value.
>
> I don't have ready access to any target that would be affected by this
> patch, so I'm asking for volunteers to do some testing.
Tests OK on mips64octeon-linux-gnu (all 3 ABIs). But I think the
patch is too aggressive. The case Mark was worried about was when:
mode1 != mode2 != mode3
and where the mode1->mode2 (language) promotion was different from the
mode2->mode3 (ABI) promotion. So I think the problem with the earlier
patch was that it checked "uns1 == uns3" unconditionally, rather than
when "mode1 != mode2". I.e. I think we should be checking something
like this instead:
if (mode1 != mode3
&& mode3 == mode4
&& (mode1 == mode2 || (uns1 == uns3 && strictly_local)))
The following test catches the difference, and regresses if we
remove the "uns1 == uns3" check completely:
-----------------------------
static long long __attribute__((noinline)) foo (unsigned short s)
{
return (short) s;
}
unsigned short s = 0xFFFF;
int
main (void)
{
return foo (s) + 1 != 0;
}
-----------------------------
Richard