On 10/5/23 07:33, Robin Dapp wrote:
So I think Kenner's code is trying to prevent having a value in a
SUBREG that is inconsistent with the SUBREG_PROMOTED* flag bits. But
I think it's been unnecessary since Matz's rewrite in 2009.
I couldn't really tell what the rewrite does entirely so I tried creating
a case where we would require the SUBREG_PROMOTED_VAR but couldn't come
up with any. At least for the most common path through expr I believe
I know why:
So our case is when we have an SI subreg from a DI reg that is originally
a sign-extended SI. Then we NOP-convert the SI subreg from signed to
unsigned. We only perform implicit sign extensions therefore we can
omit the implicit zero-extension case here.
Right. The extension into bits 32..63, whether it be zero or sign
extension is essentially a don't care. It's there because of
PROMOTE_MODE forcing most operations to 64 bits to match the hardware,
even if the upper 32 bits aren't ever relevant.
The way the result of the signed->unsigned conversion is used determines
whether we can use SUBREG_PROMOTED_VAR. There are two possibilities
(1) and (2).
void foo (int bar)
{
unsigned int u = (unsigned int) bar;
(1) unsigned long long ul = (unsigned long long) u;
As long as the result is used unsigned, we will always perform a zero
extension no matter the "Kenner hunk" (because whether the subreg has
SRP_SIGNED or !SUBREG_PROMOTED_VAR does not change the need for a
zero_extend).
Right.
(2) long long l = (long long) u;
SUBREG_PROMOTED is checked by the following in convert_move:
scalar_int_mode to_int_mode;
if (GET_CODE (from) == SUBREG
&& SUBREG_PROMOTED_VAR_P (from)
&& is_a <scalar_int_mode> (to_mode, &to_int_mode)
&& (GET_MODE_PRECISION (subreg_promoted_mode (from))
>= GET_MODE_PRECISION (to_int_mode))
&& SUBREG_CHECK_PROMOTED_SIGN (from, unsignedp))
The SUBREG_CHECK_PROMOTED_SIGN (from, unsignedp) is decisive
as far as I can tell.
Right. We have already ensured the modes are either the same size or
the PARM_DECL's mode is wider than the local VAR_DECL's mode. So the
check that FROM has the same promotion property as UNSIGNEDP is going to
be decisive.
unsignedp = 1 comes from treeop0 so our
Correct. It comes from the TREE_TYPE (treeop0) where treeop0 is the
incoming PARM_DECL.
"from" (i.e. unsigned int u).
With the "Kenner hunk" SUBREG_PROMOTED_VAR is unset, so we don't
strip the extension. Without it, SUBREG_PROMOTED_VAR () == SRP_SIGNED
which is != unsignedp, so no stripping either.
Correct. The Kenner hunk wipes SUBREG_PROMOTED_VAR, meaning the
promotion state of the object is unknown.
Now there are several other paths that would need auditing as well
but at least this one is safe. An interesting test target would be
a backend that does implicit zero extensions but as we haven't seen
fallout so far chances to find a trigger are slim.
I did some testing of the other paths yesterday, but didn't include them
in my message.
First, if the PARM_DECL is a narrower type than the local VAR_DECL, then
the path we're considering changing doesn't get used because the modes
have different sizes. Thus we need not worry about this case.
If the PARM_DECL is wider than the local VAR_DECL, then we downsize to
the same size as the VAR_DECL via a SUBREG and it behaves the same as
the Vineet's original when the sizes are the same, but they differ in
signedness. So if we conclude the same size cases are OK, then the case
where the PARM_DECL is wider than the VAR_DECL, we're going to be safe
as well.
Jeff