Benutzen wir Julia, können wir mittels Introspection ansehen, was für Code LLVM aus unseren Beispielen zaubert. Dazu definieren wir zunächst wieder die zwei Varianten unseres max-Beispiels:

function max(a,b)
    if(a>b)
        return a
    else
       return b
end

function max1(a,b) return a*(a>b)+b*(a<=b) end

Mittels code_native(max,(Int,Int)) bzw code_native(max1,(Int,Int)) können wir uns nun ansehen, was LLVM für Code daraus produziert - zunächst wieder die "normale" Variante:

code_native(max,(Int,Int))
        .text
Filename: promotion.jl
Source line: 239
        pushq   %rbp
        movq    %rsp, %rbp
        cmpq    %rdi, %rsi
Source line: 239
        cmovgeq %rsi, %rdi
        movq    %rdi, %rax
        popq    %rbp
        ret

Und die branchless-Variante:

code_native(max1,(Int,Int))
        .text
Filename: none
Source line: 2
        pushq   %rbp
        movq    %rsp, %rbp
        xorl    %eax, %eax
        cmpq    %rsi, %rdi
Source line: 2
        movq    %rsi, %rcx
        cmovgq  %rax, %rcx
        cmpq    %rdi, %rsi
        cmovlq  %rdi, %rax
        addq    %rcx, %rax
        popq    %rbp
        ret

Hier zeigt sich wieder, was wir bereits mit GCC auf x86 und ARM festgestellt haben: Triviale Beispiele behandelt der Compiler effektiver als es unser Code aus der Manufaktur kann. Wie sieht es aber mit dem nicht mehr so trivialen Beispiel aus?

function nontriv(a)
    for i in 1:length(a)
        pointedAt=a[i]
        if((pointedAt>=97)&&(pointedAt<=122))
            a[i]=pointedAt-32
        end
    end
end

function nontriv1(a) for i in 1:length(a) pointedAt=a[i] x=((pointedAt>=97)&&(pointedAt<=122)) a[i]=pointedAt-(32*x) end end

Hier zeigt sich bei Aufruf von code_native(nontriv,(Tuple{Array{Int,1}})) zunächst erst einmal, dass es offenbar doch keine gute Idee war, die beiden Compiler mittels Abkürzung über Julias Introspect-Mechanismus vergleichen zu wollen: Dieser Mechanismus zeigt nicht einfach nur den Maschinencode, sondern tut offenbar noch mehr - anders ist nicht zu erklären, dass verschiedene Quelltext-Zeilen mehr als einmal im Ergebnis auftauchen:

code_native(nontriv,(Tuple{Array{Int,1}}))
        .text
Filename: none
Source line: 2
        pushq   %rbp
        movq    %rsp, %rbp
Source line: 2
        movq    8(%rdi), %r9
        xorl    %ecx, %ecx
        testq   %r9, %r9
        movl    $0, %eax
        cmovnsq %r9, %rax
        testq   %rax, %rax
        je      L123
Source line: 5
        testq   %r9, %r9
        cmovsq  %rcx, %r9
Source line: 2
        negq    %r9
Source line: 3
        movq    8(%rdi), %r8
        xorl    %edx, %edx
L47:    cmpq    %r8, %rcx
        jae     L128
        movq    (%rdi), %r10
Source line: 5
        leaq    (,%rdx,8), %rax
        negq    %rax
Source line: 3
        movq    (%r10,%rax), %rax
        cmpq    $97, %rax
Source line: 4
        jl      L108
        cmpq    $122, %rax
        jg      L108
Source line: 3
        movq    %rdx, %rsi
        negq    %rsi
Source line: 5
        addq    $-32, %rax
        movq    %rax, (%r10,%rsi,8)
L108:   incq    %rcx
        decq    %rdx
        cmpq    %rdx, %r9
        jne     L47
L123:   movq    %rbp, %rsp
        popq    %rbp
        ret
L128:   movl    $1, %eax
Source line: 3
        subq    %rdx, %rax
        movq    %rsp, %rcx
        leaq    -16(%rcx), %rsi
        movq    %rsi, %rsp
        movq    %rax, -16(%rcx)
        movabsq $jl_bounds_error_ints, %rax
        movl    $1, %edx
        callq   *%rax

Auch der Aufruf von code_native(nontriv1,(Tuple{Array{Int,1}})) zeigt dieses Verhalten: Manche Quelltextzeilen tauchen mehrfach auf. Insgesamt ist das Ergebnis länger als für nontriv, allerdings hat das wahrscheinlich keine Aussagekraft. Daher wurde es wohl oder übel notwendig, LLVM zu installieren und es auf den C-Quelltext anzusetzen...

code_native(nontriv1,(Tuple{Array{Int,1}}))
        .text
Filename: none
Source line: 2
        pushq   %rbp
        movq    %rsp, %rbp
Source line: 2
        movq    8(%rdi), %r9
        xorl    %r11d, %r11d
        testq   %r9, %r9
        movl    $0, %eax
        cmovnsq %r9, %rax
        testq   %rax, %rax
        je      L138
Source line: 5
        testq   %r9, %r9
        cmovsq  %r11, %r9
Source line: 2
        negq    %r9
Source line: 3
        movq    8(%rdi), %r8
        xorl    %edx, %edx
L48:    cmpq    %r8, %r11
        jae     L143
Source line: 5
        leaq    (,%rdx,8), %r10
Source line: 3
        movq    (%rdi), %rax
Source line: 5
        subq    %r10, %rax
Source line: 3
        movq    (%rax), %rax
        xorl    %esi, %esi
        cmpq    $97, %rax
Source line: 4
        jl      L100
        cmpq    $123, %rax
        setl    %cl
        movzbl  %cl, %esi
        shlq    $5, %rsi
Source line: 5
L100:   cmpq    8(%rdi), %r11
        jae     L182
        subq    %rsi, %rax
        movq    (%rdi), %rsi
        negq    %r10
        movq    %rax, (%rsi,%r10)
        incq    %r11
        decq    %rdx
        cmpq    %rdx, %r9
        jne     L48
L138:   movq    %rbp, %rsp
        popq    %rbp
        ret
L143:   movl    $1, %eax
Source line: 3
        subq    %rdx, %rax
        movq    %rsp, %rcx
        leaq    -16(%rcx), %rsi
        movq    %rsi, %rsp
        movq    %rax, -16(%rcx)
        movabsq $jl_bounds_error_ints, %rax
        movl    $1, %edx
        callq   *%rax
L182:   movl    $1, %eax
Source line: 5
        subq    %rdx, %rax
        movq    %rsp, %rcx
        leaq    -16(%rcx), %rsi
        movq    %rsi, %rsp
        movq    %rax, -16(%rcx)
        movabsq $jl_bounds_error_ints, %rax
        movl    $1, %edx
        callq   *%rax

Alle Artikel rss Wochenübersicht Monatsübersicht Github Repositories Gitlab Repositories Mastodon Über mich home xmpp


Vor 5 Jahren hier im Blog

  • Certstream, InfluxDB, Grafana und Netflix

    16.04.2019

    Nachdem ich vor kurzem über mein erstes Spielen mit dem certstream berichtete, habe ich weitere Experimente gemacht und die Daten zur besseren Auswertung in eine InfluxDB gepackt, um sie mit Grafana untersuchen zu können.

    Weiterlesen...

Neueste Artikel

  • Die sQLshell ist nun cloudnative!

    Die sQLshell hat eine weitere Integration erfahren - obwohl ich eigentlich selber nicht viel dazu tun musste: Es existiert ein Projekt/Produkt namens steampipe, dessen Slogan ist select * from cloud; - Im Prinzip eine Wrapperschicht um diverse (laut Eigenwerbung mehr als 140) (cloud) data sources.

    Weiterlesen...
  • LinkCollections 2024 III

    Nach der letzten losen Zusammenstellung (für mich) interessanter Links aus den Tiefen des Internet von 2024 folgt hier gleich die nächste:

    Weiterlesen...
  • Funktionen mit mehreren Rückgabewerten in Java

    Da ich seit nunmehr einem Jahr bei meinem neeun Arbeitgeber beschäftigt und damit seit ungefähr derselben Zeit für Geld mit Python arbeite, haben sich gewisse Antipathien gegenüber Python vertieft (ich kann mit typlosen Sprachen einfach nicht umgehen) - aber auch einige meiner Gründe, Python zu lieben sind ebenso stärker geworden. Einer davon ist der Fakt, dass eine Methode in Python mehr als einen Wert zurückgeben kann.

    Weiterlesen...

Manche nennen es Blog, manche Web-Seite - ich schreibe hier hin und wieder über meine Erlebnisse, Rückschläge und Erleuchtungen bei meinen Hobbies.

Wer daran teilhaben und eventuell sogar davon profitieren möchte, muß damit leben, daß ich hin und wieder kleine Ausflüge in Bereiche mache, die nichts mit IT, Administration oder Softwareentwicklung zu tun haben.

Ich wünsche allen Lesern viel Spaß und hin und wieder einen kleinen AHA!-Effekt...

PS: Meine öffentlichen GitHub-Repositories findet man hier - meine öffentlichen GitLab-Repositories finden sich dagegen hier.