[cft] Fix pr42269 -- loss of incoming promotions in combine
Richard Sandiford
rdsandiford@googlemail.com
Sat Dec 5 13:02:00 GMT 2009
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
More information about the Gcc-patches
mailing list