On 2/26/2022 2:35 PM, Roger Sayle wrote:
This patch resolves PR middle-end/95126 which is a code quality regression,
by teaching the RTL expander to emit small const structs/unions as integer
immediate constants.

The motivating example from the bugzilla PR is:

struct small{ short a,b; signed char c; };
extern int func(struct small X);
void call_func(void)
{
     static struct small const s = { 1, 2, 0 };
     func(s);
}

which on x86_64 is currently compiled to:

call_func:
         movzwl  s.0+2(%rip), %eax
         movzwl  s.0(%rip), %edx
         movzwl  s.0+4(%rip), %edi
         salq    $16, %rax
         orq     %rdx, %rax
         salq    $32, %rdi
         orq     %rax, %rdi
         jmp     func

but with this patch is now optimized to:

call_func:
         movl    $131073, %edi
         jmp     func


This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
and make -k check with no new failures.  Ok for mainline?


2022-02-26  Roger Sayle  <ro...@nextmovesoftware.com>

gcc/ChangeLog
        PR middle-end/95126
        * calls.cc (load_register_parameters): When loading a suitable
        immediate_const_ctor_p VAR_DECL into a single word_mode register,
        construct it directly in a pseudo rather than read it (by parts)
        from memory.
        * expr.cc (int_expr_size): Make tree argument a const_tree.
        (immediate_const_ctor_p): Helper predicate.  Return true for
        simple constructors that may be materialized in a register.
        (expand_expr_real_1) [VAR_DECL]: When expanding a constant
        VAR_DECL with a suitable immediate_const_ctor_p constructor
        use store_constructor to materialize it directly in a pseudo.
        * expr.h (immediate_const_ctor_p): Prototype here.
        * varasm.cc (initializer_constant_valid_for_bitfield_p): Change
        VALUE argument from tree to const_tree.
        * varasm.h (initializer_constant_valid_for_bitfield_p): Update
        prototype.

gcc/testsuite/ChangeLog
        PR middle-end/95126
        * gcc.target/i386/pr95126-m32-1.c: New test case.
        * gcc.target/i386/pr95126-m32-2.c: New test case.
        * gcc.target/i386/pr95126-m32-3.c: New test case.
        * gcc.target/i386/pr95126-m32-4.c: New test case.
        * gcc.target/i386/pr95126-m64-1.c: New test case.
        * gcc.target/i386/pr95126-m64-2.c: New test case.
        * gcc.target/i386/pr95126-m64-3.c: New test case.
        * gcc.target/i386/pr95126-m64-4.c: New test case.
OK after a fresh bootstrap & regression test.  Sorry for the long wait.

jeff

Reply via email to