Hi Alex!

You might perhaps have noticed, that modern CPUs execute "unoptimized"
compiler code almost as fast as code produced by highly optimizing
compilers (-Os vs. -O3). Difference is almost zero!

You also might have noticed, that AMD with EPYC Rome and Threadripper are
far ahead of Intel in terms of IPC - Instructions Per Clockcycle.

That has to do with long instruction prefetch queues, a new neural "branch
prediction" and new, highly sophisticated translators from ISA instructions
into internal microcode.

I can tell you, that "SSA" tricks, such as PHI() optimizations, "register
renaming", ... all that stuff alredy has moved into the processor itself. 2
megabytes (that's the size of a full processor microcode update!) of
processor - internal "post machine code optimization" - code makes that
possible.

On AMD EPYC, even speed of completely unoptimized TCC machine code comes
quite close to - hundreds of years of intelligent man/womenpower optimized
- GCC/LLVM compiler code. Difference is negligible.

https://en.wikipedia.org/wiki/Static_single_assignment_form

These "SSA idea" is going back to 1988. Today is 2020, that's 32 years
later.

Have fun!

Guido Stepken

Am Sonntag, 12. April 2020 schrieb Alexander Burger <a...@software-lab.de>:
> On Sun, Apr 12, 2020 at 08:09:46AM +0200, Tomas Hlavaty wrote:
>> Rowan Thorpe <ro...@rowanthorpe.com> writes:
>> > parentheses are not used because as is stated at
>> > https://picolisp.com/wiki/?src64 "Assembly language is not a
>> > functional language, i.e. the individual instructions do not "return"
>> > a value. So a fully parenthesized syntax is useless and just tedious."
>>
>> because picolisp doesn't have a compiler (program)
>>
>> it is "compiled" to the picolisp assembly manually ahead of time by Alex
>> (human)
>
> Actually, all this will change with the new PicoLisp "pil21". It is no
longer
> oriented to machine *instructions* like pil64, but to SSA (Static Single
> Assignment) *values*.
>
> It is a radically different approach. If there is interest, work in
progress can
> be seen at
>
>    https://git.envs.net/mpech/pil21
>
> or directly in
>
>    https://software-lab.de/pil21.tgz
>
> Here the sources have real PicoLisp syntax (though partially different
> semantics). The compiler (in "src/lib/llvm.l") does not only use the
reader, but
> generates the LLVM-IR by *executing* the code (Forth is chuckling from
behind).
>
> This works by simply redefining some (not many) functions in llvm' and
'priv'
> namespaces.
>
>
> For example, the source of the 'car' function:
>
> In pil64 it is (in "src64/subr.l")
>
>    # (car 'var) -> any
>    (code 'doCar 2)
>       push X
>       ld X E
>       ld E ((E CDR))  # Get arg
>       eval
>       num E  # Need variable
>       jnz varErrEX
>       ld E (E)  # Take CAR
>       pop X
>       ret
>
> This results in e.g. AMD/Intel asssembly (in "src64/x86-64.linux.base.s")
>
>       .globl  doCar
>    doCar:
>       push     %r13
>       mov      %rbx, %r13
>       mov      8(%rbx), %r10
>       mov      (%r10), %rbx
>       test     $0x06, %bl
>       jnz      1f
>       test     $0x08, %bl
>       cmovnzq  (%rbx), %rbx
>       jnz      1f
>       call     evListE_E
>    1:
>       testb    $0x06, %bl
>       jnz      varErrEX
>       mov      (%rbx), %rbx
>       pop      %r13
>       ret
>
>
> Now in pil21 the source is (in "src/subr.l"):
>
>    # (car 'var) -> any
>    (de _car (Exe)
>       (car (needVar Exe (eval (cadr Exe)))) )
>
> and the result in LLVM-IR is (in "src/base.ll"):
>
>    define i64 @_car(i64) {
>    $1:
>    ; # (cadr Exe)
>      %1 = inttoptr i64 %0 to i64*
>      %2 = getelementptr i64, i64* %1, i32 1
>      %3 = load i64, i64* %2
>      %4 = inttoptr i64 %3 to i64*
>      %5 = load i64, i64* %4
>    ; # (eval (cadr Exe))
>      %6 = and i64 %5, 6
>      %7 = icmp ne i64 %6, 0
>      br i1 %7, label %$4, label %$3
>    $4:
>      br label %$2
>    $3:
>      %8 = and i64 %5, 8
>      %9 = icmp ne i64 %8, 0
>      br i1 %9, label %$6, label %$5
>    $6:
>      %10 = inttoptr i64 %5 to i64*
>      %11 = load i64, i64* %10
>      br label %$2
>    $5:
>      %12 = call i64 @evList(i64 %5)
>      br label %$2
>    $2:
>      %13 = phi i64 [%5, %$4], [%11, %$6], [%12, %$5] ; # ->
>    ; # (needVar Exe (eval (cadr Exe)))
>      %14 = and i64 %13, 6
>      %15 = icmp ne i64 %14, 0
>      br i1 %15, label %$7, label %$8
>    $7:
>      call void @varErr(i64 %0, i64 %13)
>      unreachable
>    $8:
>    ; # (car (needVar Exe (eval (cadr Exe))))
>      %16 = inttoptr i64 %13 to i64*
>      %17 = load i64, i64* %16
>      ret i64 %17
>    }
>
> Looks unbelievably horrible, but works ;)
>
> ☺/ A!ex
>
> --
> UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
>

Reply via email to