Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2021-07

Potential whole program optimization

3 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

J. Gareth Moreton

Hi everyone,

I've been playing around with the peephole optimizer on x86_64 a lot lately, and I'm starting to notice that a lot of procedures, both in the RTL and the compiler itself, produce the same assembly language when fully optimized (or sometimes even before this point).  Just as an example in the assembly for TStream in the classes unit:

.section .text.n_classes$_$tstream_$__$$_readdata$char$$nativeint,"ax"     .balign 16,0x90
.globl    CLASSES$_$TSTREAM_$__$$_READDATA$CHAR$$NATIVEINT CLASSES$_$TSTREAM_$__$$_READDATA$CHAR$$NATIVEINT:
.seh_proc CLASSES$_$TSTREAM_$__$$_READDATA$CHAR$$NATIVEINT     leaq    -40(%rsp),%rsp
.seh_stackalloc 40
.seh_endprologue
# Peephole Optimization: Mov2Nop 3b done
    movl    $1,%r8d
# Peephole Optimization: %rcx = %rax; removed unnecessary instruction (MovMov2MovNop 6b}
# Peephole Optimization: %rax = %rcx; changed to minimise pipeline stall (MovXXX2MovXXX)
    movq    (%rcx),%rax
    call    *256(%rax)
    movslq  %eax,%rax
    nop
    leaq    40(%rsp),%rsp
    ret
.seh_endproc

.section .text.n_classes$_$tstream_$__$$_readdata$shortint$$nativeint,"ax"     .balign 16,0x90
.globl    CLASSES$_$TSTREAM_$__$$_READDATA$SHORTINT$$NATIVEINT CLASSES$_$TSTREAM_$__$$_READDATA$SHORTINT$$NATIVEINT: .seh_proc CLASSES$_$TSTREAM_$__$$_READDATA$SHORTINT$$NATIVEINT     leaq    -40(%rsp),%rsp
.seh_stackalloc 40
.seh_endprologue
# Peephole Optimization: Mov2Nop 3b done
    movl    $1,%r8d
# Peephole Optimization: %rcx = %rax; removed unnecessary instruction (MovMov2MovNop 6b}
# Peephole Optimization: %rax = %rcx; changed to minimise pipeline stall (MovXXX2MovXXX)
    movq    (%rcx),%rax
    call    *256(%rax)
    movslq  %eax,%rax
    nop
    leaq    40(%rsp),%rsp
    ret
.seh_endproc

.section .text.n_classes$_$tstream_$__$$_readdata$byte$$nativeint,"ax"     .balign 16,0x90
.globl    CLASSES$_$TSTREAM_$__$$_READDATA$BYTE$$NATIVEINT CLASSES$_$TSTREAM_$__$$_READDATA$BYTE$$NATIVEINT:
.seh_proc CLASSES$_$TSTREAM_$__$$_READDATA$BYTE$$NATIVEINT     leaq    -40(%rsp),%rsp
.seh_stackalloc 40
.seh_endprologue
# Peephole Optimization: Mov2Nop 3b done
    movl    $1,%r8d
# Peephole Optimization: %rcx = %rax; removed unnecessary instruction (MovMov2MovNop 6b}
# Peephole Optimization: %rax = %rcx; changed to minimise pipeline stall (MovXXX2MovXXX)
    movq    (%rcx),%rax
    call    *256(%rax)
    movslq  %eax,%rax
    nop
    leaq    40(%rsp),%rsp
    ret
.seh_endproc

The final assembly language of each method is identical.

(Note that the trunk is not this efficient just yet... it still leaves a "movq %rcx,%rax" instruction prior to "movl $1,%r8d" and then calls "movq (%rax),%rax" instead of "movq (%rcx),%rax" - it's still all identical though).

Would it be plausible to calculate and store a form of message digest (hash) of the final form of the tai entries or machine code and identify collisions and potential duplicate procedures for whole-program optimization? Granted I don't know anything about WPO yet so I don't know how plausible this is.  This wouldn't be somethind done on quick or debug builds because you'll need to be able to do proper stack traces, and having identical procedures merged into one might cause confusion.

Gareth aka. Kit

This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

Martin Frb
to J. Gareth Moreton
J. Gareth Moreton wrote 16 lines
The final assembly language of each method is identical. (Note that the trunk is not this efficient just yet... it still leaves a "movq %rcx,%rax" instruction prior to "movl $1,%r8d" and then calls "movq (%rax),%rax" instead of "movq (%rcx),%rax" - it's still all identical though). Would it be plausible to calculate and store a form of message digest (hash) of the final form of the tai entries or machine code and identify collisions and potential duplicate procedures for whole-program optimization? Granted I don't know anything about WPO yet so I don't know how plausible this is.  This wouldn't be somethind done on quick or debug builds because you'll need to be able to do proper stack traces, and having identical procedures merged into one might cause confusion.

Why WPO?

When you compute this hash, you could immediately check if it already exists. (either in this unit, or any unit used).

The only miss would be, if 2 units, that do not see each other include identical code. That part could then still be a WPO.

Reply by email

J. Gareth Moreton
to Martin Frb

I mention WPO because of other procedures calling them.  It would be very impractical to go back to procedures that have already gone through the peephole optimizer etc and change the references, especially if said reference is converted into a raw offset (I'm not absolutely sure when it's converted into a raw offset and when it's a reference that's converted by the assembler).

Gareth aka. Kit

Martin Frb wrote 29 lines
On 19/07/2021 01:24, J. Gareth Moreton via fpc-devel wrote: > > The final assembly language of each method is identical. > > (Note that the trunk is not this efficient just yet... it still > leaves a "movq %rcx,%rax" instruction prior to "movl $1,%r8d" and > then calls "movq (%rax),%rax" instead of "movq (%rcx),%rax" - it's > still all identical though). > > Would it be plausible to calculate and store a form of message digest > (hash) of the final form of the tai entries or machine code and > identify collisions and potential duplicate procedures for > whole-program optimization? Granted I don't know anything about WPO > yet so I don't know how plausible this is.  This wouldn't be > somethind done on quick or debug builds because you'll need to be > able to do proper stack traces, and having identical procedures > merged into one might cause confusion. Why WPO? When you compute this hash, you could immediately check if it already exists. (either in this unit, or any unit used). The only miss would be, if 2 units, that do not see each other include identical code. That part could then still be a WPO. _______________________________________________ fpc-devel maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email