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.