On Mon, Jun 22, 2026 at 1:29 PM Uros Bizjak <[email protected]> wrote:
>
> On Mon, Jun 22, 2026 at 8:33 AM H.J. Lu <[email protected]> wrote:
> >
> > On Mon, Jun 22, 2026 at 1:59 PM Uros Bizjak <[email protected]> wrote:
> > >
> > > -ENOPATCH
> >
> > Oops.  Here it is.
> >
> > > On Sun, Jun 21, 2026 at 11:44 PM H.J. Lu <[email protected]> wrote:
> > > >
> > > > Since LCP stall peepholes are added after register allocation, each
> > > > peephole may use a different scratch register.  For input:
> > > >
> > > > extern void bar (void);
> > > >
> > > > void
> > > > foo (short *dst)
> > > > {
> > > >   dst[0] = 3;
> > > >   asm volatile ("" : : : "memory");
> > > >   dst[2] = 3;
> > > >   bar ();
> > > >   dst[1] = 3;
> > > >   asm volatile ("" : : : "memory");
> > > >   dst[4] = 3;
> > > > }
> > > >
> > > > with LCP stall peepholes, GCC generates:
> > > >
> > > > movl $3, %eax
> > > > pushq %rbx
> > > > movq %rdi, %rbx
> > > > movw %ax, (%rdi)
> > > > movl $3, %edx
> > > > movw %dx, 4(%rdi)
> > > > call bar
> > > > movl $3, %ecx
> > > > movw %cx, 2(%rbx)
> > > > movl $3, %esi
> > > > movw %si, 8(%rbx)
> > > > popq %rbx
> > > >
> > > > using 4 different scratch registers vs without LCP stall peepholes:
> > > >
> > > > pushq %rbx
> > > > movq %rdi, %rbx
> > > > movw $3, (%rdi)
> > > > movw $3, 4(%rdi)
> > > > call bar
> > > > movw $3, 2(%rbx)
> > > > movw $3, 8(%rbx)
> > > > popq %rbx
> > > >
> > > > Add ix86_output_lcp_stall_peephole to generate LCP stall peepholes with
> > > > the previous scratch register:
> > > >
> > > > 1. Scan backward for the previous scratch register definition with
> > > > the same immediate operand in the same basic block.
> > > > 2. The previous scratch register is unusable if it is set between the
> > > > previous scratch register definition and the current instruction.
> > > > 3. If a usable previous scratch register is found, ignore the allocated
> > > > scratch register and use the previous scratch register.  Otherwise, use
> > > > the allocated scratch register.
> > > >
> > > > so that the same scratch register can be reused if possible:
> > > >
> > > > movl $3, %eax
> > > > pushq %rbx
> > > > movq %rdi, %rbx
> > > > movw %ax, (%rdi)
> > > > movw %ax, 4(%rdi)
> > > > call bar
> > > > movl $3, %ecx
> > > > movw %cx, 2(%rbx)
> > > > movw %cx, 8(%rbx)
> > > > popq %rbx
> > > >
> > > > I backported this patch to GCC 16:
> > > >
> > > > 1. When bootstrapping GCC 16 with only C and C++ enabled, this 
> > > > optimization
> > > > triggers 54 times.  No regressions.
> > > > 2. When building glibc 2.44, this optimization triggers 33 times.  No
> > > > regressions.
> > > > 3. When building Linux kernel 7.1.1, this optimization triggers 2099 
> > > > times.
> > > > Kernel boots correctly.
> > > >
> > > > gcc/
> > > >
> > > > PR target/125893
> > > > * config/i386/i386-protos.h (ix86_output_lcp_stall_peephole):
> > > > New.
> > > > * config/i386/i386.cc (ix86_output_lcp_stall_peephole): Likewise.
> > > > * config/i386/i386.md (TARGET_LCP_STALL peepholes): Call
> > > > ix86_output_lcp_stall_peephole.
> > > >
> > > > gcc/testsuite/
> > > >
> > > > PR target/125893
> > > > * gcc.target/i386/pr125893-1.c: New test.
> > > > * gcc.target/i386/pr125893-2.c: Likewise.
> > > > * gcc.target/i386/pr125893-3.c: Likewise.
> > > > * gcc.target/i386/pr125893-4.c: Likewise.
> > > > * gcc.target/i386/pr125893-5.c: Likewise.
> > > > * gcc.target/i386/pr125893-6.c: Likewise.
> > > > * gcc.target/i386/pr125893-7.c: Likewise.
> > > > * gcc.target/i386/pr125893-8.c: Likewise.
> > > > * gcc.target/i386/pr125893-9.c: Likewise.
> > > > * gcc.target/i386/pr125893-10.c: Likewise.
>
>
> +/* Output LCP stall or long immediate peephole for INSN.  Use the
> +   previous scratch register if possible.  */
> +
> +void
> +ix86_output_lcp_stall_peephole (rtx_insn *insn, rtx *operands)
> +{
>
> Please name this function ix86_expand_lcp_stall_peephole. We are
> expanding RTXes here, not outputting ASM.
>
> -  [(parallel [(set (match_dup 2) (const_int 0))
> -          (clobber (reg:CC FLAGS_REG))])
> -   (set (match_dup 0) (match_dup 1))]
> -  "operands[2] = gen_lowpart (SImode, operands[1]);")
> +  [(const_int 0)]
> +{
> +  operands[2] = const0_rtx;
> +  ix86_output_lcp_stall_peephole (curr_insn, operands);
> +})
>
> Missing DONE;
>
> -  [(set (match_dup 2) (match_dup 1))
> -   (set (match_dup 0) (match_dup 2))])
> +  [(const_int 0)]
> +  "ix86_output_lcp_stall_peephole (curr_insn, operands);")
>
> Also here.
>
> On a related note, the second peephole also allows const0_rtx, which
> results in XOR form, which clobbers flags. Please better use some
> boolean argument (e.g. use_xor) to the ix86_output_lcp_stall_peephole
> and handle it accordingly in both peephole2 patterns.

Another observation: You can't reuse %esi/%edi/%ebp/%esp as QImode
scratch in 32-bit mode. So, the value, available in one of these
registers, can not be reused as QImode value. Please re-test the patch
also for 32-bit mode.

Uros.

Reply via email to