On Mon, May 5, 2025 at 7:32 AM H.J. Lu <hjl.to...@gmail.com> wrote:

> Here is the v2 patch.   ix86_get_small_integer_argument_value was moved to
> calls.cc.  I added a target hook, TARGET_SAME_FUNCTION_ARGUMENT_ORDER_P,
> to verify that caller and callee have the same incoming argument
> order.  The default returns
> true.  The x86 hook has
>
> /* Implement TARGET_SAME_INCOMING_ARGUMENT_ORDER_P.  */
>
> static bool
> ix86_same_incoming_argument_order_p (const_tree fndecl)
> {
>   return (!TARGET_64BIT
>           || (ix86_function_abi (current_function_decl)
>               == ix86_function_abi (fndecl)));
> }
>
> since 64-bit SYSV ABI and 64-bit MS ABI have different argument orders.
> Copying one incoming argument register to another outgoing argument register
> may override the other incoming argument register.
>
> --
> H.J.
> ---
> or targets, like x86, which define TARGET_PROMOTE_PROTOTYPES to return
> true, all integer arguments smaller than int are passed as int:
>
> [hjl@gnu-tgl-3 pr14907]$ cat x.c
> extern int baz (char c1);
>
> int
> foo (char c1)
> {
>   return baz (c1);
> }
> [hjl@gnu-tgl-3 pr14907]$ gcc -S -O2 -m32 x.c
> [hjl@gnu-tgl-3 pr14907]$ cat x.s
> .file "x.c"
> .text
> .p2align 4
> .globl foo
> .type foo, @function
> foo:
> .LFB0:
> .cfi_startproc
> movsbl 4(%esp), %eax
> movl %eax, 4(%esp)
> jmp baz
> .cfi_endproc
> .LFE0:
> .size foo, .-foo
> .ident "GCC: (GNU) 14.2.1 20240912 (Red Hat 14.2.1-3)"
> .section .note.GNU-stack,"",@progbits
> [hjl@gnu-tgl-3 pr14907]$
>
> But integer promotion:
>
> movsbl 4(%esp), %eax
> movl %eax, 4(%esp)
>
> isn't necessary if incoming arguments are copied to outgoing arguments
> directly.
>
> We can use the incoming argument value as the outgoing argument as if it
> has been promoted if
>
> 1. Caller and callee are not nested functions.
> 2. Caller and callee have the same incoming argument order.  Add a new
> target hook, TARGET_SAME_FUNCTION_ARGUMENT_ORDER_P, which returns true
> if caller and callee have the same incoming argument order.  If the
> incoming argument order of the caller is different from the incoming
> argument order of the callee since the same register may be used for
> different incoming arguments in caller and callee.  Copying from one
> incoming argument in the caller to an outgoing argument may override
> another incoming argument.
> 3. The incoming argument is unchanged before call expansion.
>
> Otherwise, using the incoming argument as the outgoing argument may change
> values of other incoming arguments or the wrong outgoing argument value
> may be used.
>
> If callee is a global function, we always properly extend the incoming
> small integer arguments in callee.  If callee is a local function, since
> DECL_ARG_TYPE has the original small integer type, we will extend the
> incoming small integer arguments in callee if needed.
>
> Tested on x86-64, x32 and i686.
>
> NB: I tried to elide all incoming argument copying for all types, not
> just integer arguments smaller than int.  But GCC was miscompiled which
> is related to function inlining.  There is
>
> foo
>   call baz
>
> bar
>   call foo
>
> when foo is inlined
>
> bar
>    call baz
>
> the incoming arguments, which aren't integer arguments smaller than int,
> for baz get the wrong values sometimes.

Here is the v3 patch.  The difference from v2 is to use

          if (MEM_P (src)
              && MEM_EXPR (src)
              && (TREE_CODE (get_base_address (MEM_EXPR (src)))
                  == PARM_DECL))
            continue;

to check incoming arguments on stack.

OK for master?

Thanks.

-- 
H.J.

Reply via email to