Elimination of duplicate sign extensions

Mark Mitchell mark@codesourcery.com
Tue Sep 11 23:20:00 GMT 2007


Mark Shinwell wrote:
> The generated code for f originally looks like:
> 
>         sll     $2,$4,16
>         sra     $2,$2,16
>         j       $31
>         slt     $2,$0,$2
> 
> After this patch, we end up with just:
> 
>         j       $31
>         slt     $2,$0,$4

Nice!

To be clear, the case where the optimization you're working on is
interesting is when the ABI does not require that callers sign-extend
arguments to functions -- but we do it anyhow.  Is that correct?

So, if we can't see all the callers, we have to actually perform the
sign extension; someone might not have sign-extended at the call-site,
so we have to do so in the function body.  But, if all the calls are
from within the same translation unit, then we know that calls to this
function will have had their arguments promoted, and, therefore, that we
don't need to do so in the callee.  Is that right?

> Before this patch, combine only causes such sign extensions to be
> eliminated when the TYPE_MODEs of the container and argument types
> match.

(This code looks a little funny to me, even before your change.  In
particular, we do this check for any argument whose RTL is a REG.  Then,
if the TYPE_MODE comparision is true, we look at TYPE_UNSIGNED.  But, a
RECORD_TYPE can have HImode, and be passed in registers, in some ABIs.
For example:

  struct S { short i; };
  void f(struct S s) {}

Here, of course, TYPE_UNSIGNED has no meaning.  I guess it just doesn't
matter; we let you check TYPE_UNSIGNED, it's probably always false, and
things work out OK.  But, it seems odd.)

> This patch relaxes that restriction, insisting instead
> that just the TREE_CODEs of those types match, but only when we can
> deduce that the function is only called from the current compilation
> unit (and so when -fno-unit-at-a-time is not in effect).

When can the TREE_CODEs not match?  Perhaps a case like this:

  /* K&R C... */
  enum E { a };
  void f(e)
    enum E e;
  {
  }

Here, the DECL_ARG_TYPE might be an INTEGER_TYPE, but the TREE_TYPE will
be a ENUMERAL_TYPE?  But, in that case, if promotions are done, the same
trick you're using would apply.  In the completely-local case, do you
need any check at all?

Thanks,

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713



More information about the Gcc-patches mailing list