On Tue, Nov 5, 2024 at 8:48 AM Jeff Law <[email protected]> wrote:
>
>
>
> On 11/4/24 5:42 PM, H.J. Lu wrote:
> > On Tue, Nov 5, 2024 at 8:07 AM Jeff Law <[email protected]> wrote:
> >>
> >>
> >>
> >> On 11/1/24 4:32 PM, H.J. Lu wrote:
> >>> For 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 and outgoing arguments are the
> >>> same. Use unpromoted incoming integer arguments as outgoing arguments
> >>> if incoming integer arguments are the same as outgoing arguments to
> >>> avoid unnecessary integer promotion.
> >> Is there a particular reason x86 can't use the same mechanisms that
> >
> > Other targets define TARGET_PROMOTE_PROTOTYPES to return false
> > to avoid this issue. Changing x86 TARGET_PROMOTE_PROTOTYPES
> > to return false will break LLVM which assumes that incoming char/short
> > arguments on x86 are always extended to int. The following targets
> Then my suggestion would be to cover this in REE somehow. We started
> looking at that a couple years ago and set it aside. But the basic
> idea was to expose the ABI guarantees to REE, then let REE do its thing.
>
> Jeff
>
For
extern int baz (char c1);
int
foo (char c1)
{
return baz (c1);
}
on i386, we get these
(insn 7 4 8 2 (set (reg:SI 0 ax [orig:102 c1 ] [102])
(sign_extend:SI (mem/c:QI (plus:SI (reg/f:SI 7 sp)
(const_int 4 [0x4])) [0 c1+0 S1 A32]))) "x.c":6:10
190 {extendqisi2}
(expr_list:REG_EQUIV (mem:SI (reg/f:SI 16 argp) [0 S4 A32])
(nil)))
(insn 8 7 9 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
(const_int 4 [0x4])) [0 S4 A32])
(reg:SI 0 ax [orig:102 c1 ] [102])) "x.c":6:10 95 {*movsi_internal}
(nil))
(call_insn/j 9 8 10 2 (set (reg:SI 0 ax)
(call (mem:QI (symbol_ref:SI ("baz") [flags 0x41]
<function_decl 0x7f27347aae00
baz>) [0 baz S1 A8])
(const_int 4 [0x4]))) "x.c":6:10 1420 {*sibcall_value}
(expr_list:REG_CALL_DECL (symbol_ref:SI ("baz") [flags 0x41]
<function_decl 0x7f273
47aae00 baz>)
(nil))
(expr_list:SI (use (mem:SI (reg/f:SI 16 argp) [0 S4 A32]))
(nil)))
before REE. How should REE work to elimate
(insn 7 4 8 2 (set (reg:SI 0 ax [orig:102 c1 ] [102])
(sign_extend:SI (mem/c:QI (plus:SI (reg/f:SI 7 sp)
(const_int 4 [0x4])) [0 c1+0 S1 A32]))) "x.c":6:10
190 {extendqisi2}
(expr_list:REG_EQUIV (mem:SI (reg/f:SI 16 argp) [0 S4 A32])
(nil)))
(insn 8 7 9 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
(const_int 4 [0x4])) [0 S4 A32])
(reg:SI 0 ax [orig:102 c1 ] [102])) "x.c":6:10 95 {*movsi_internal}
(nil))
--
H.J.