Rust: Noalias-Anmerkungen standardmĂ€ĂŸig wieder aktivieren, sobald LLVM sie nicht mehr falsch kompiliert

Erstellt am 6. Okt. 2018  Â·  33Kommentare  Â·  Quelle: rust-lang/rust

Dieses Problem verfolgt das RĂŒckgĂ€ngigmachen des -Zmutable-alias=no Standards, der in https://github.com/rust-lang/rust/pull/54639 aufgrund eines Fehlers in LLVM eingefĂŒhrt wurde. cc @nagisa

( DĂ©jĂ -vu? )

A-LLVM A-codegen C-tracking-issue I-slow T-compiler

Hilfreichster Kommentar

Ich habe es auf einen einfachen C-Testfall reduziert (bei -O3 und -O0 kompilieren und die Ausgabe vergleichen):

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

__attribute__((always_inline))
static inline void copy(int *restrict a, int *restrict b) {
    assert(a != b);
    *b = *a;
    *a = 7;
}

__attribute__((noinline))
void floppy(int mat[static 2], size_t idxs[static 3]) {
    for (int i = 0; i < 3; i++) {
        copy(&mat[i%2], &mat[idxs[i]]);
    }
}

int main() {
    int mat[3] = {10, 20};
    size_t idxs[3] = {1, 0, 1};
    floppy(mat, idxs);
    printf("%d %d\n", mat[0], mat[1]);
}

Beachten Sie, dass das Verhalten korrekt ist, wenn Sie restrict entfernen, das C-Äquivalent von noalias . Aber selbst dann passiert das assert(a != b) , was beweist, dass kein UB auftreten kann, weil es mit restrict .

Was passiert ist:

  1. copy() wird inline eingefĂŒgt, was in etwa zu folgendem Ergebnis fĂŒhrt:
for (int i = 0; i < 3; i++) {
    mat[idxs[i]] = mat[i%2]; mat[i%2] = 7;
}
  1. LLVM entrollt die Schleife:
mat[idxs[0]] = mat[0]; mat[0] = 7; /* from copy(&mat[0%2], &mat[idxs[0]]) */
mat[idxs[1]] = mat[1]; mat[1] = 7; /* from copy(&mat[1%2], &mat[idxs[1]]) */
mat[idxs[2]] = mat[0]; mat[0] = 7; /* from copy(&mat[2%2], &mat[idxs[2]]) */
  1. LLVM denkt, dass mat[0] kein Alias ​​mit mat[idxs[1]] oder mat[1] , ergo kann es nicht zwischen mat[0] = 7; und mat[idxs[2]] = mat[0]; geĂ€ndert worden sein, ergo ist es sicher fĂŒr globale Wertnummerierung, um letztere auf mat[idxs[2]] = 7; zu optimieren.

Aber mat[0] macht ein Alias ​​mit mat[idxs[1]] , weil idxs[1] == 0 . Und wir haben nicht versprochen, dass dies nicht der Fall ist, denn in der zweiten Iteration, wenn &mat[idxs[1]] an copy , ist das andere Argument &mat[1] . Warum denkt LLVM, dass dies nicht möglich ist?

Nun, es hat damit zu tun, wie copy eingebunden ist. Das Funktionsattribut noalias wird in !alias.scope und !noalias Metadaten fĂŒr die Lade- und Speicheranweisungen umgewandelt, wie:

  %8 = load i32, i32* %0, align 4, !tbaa !8, !alias.scope !10, !noalias !13
  store i32 %8, i32* %7, align 4, !tbaa !8, !alias.scope !13, !noalias !10
  store i32 7, i32* %0, align 4, !tbaa !8, !alias.scope !10, !noalias !13

Wenn eine Funktion mehrmals inline eingebunden ist, erhĂ€lt jede Kopie normalerweise ihre eigenen eindeutigen IDs fĂŒr alias.scope und noalias, was darauf hinweist, dass jeder Aufruf seine eigene 'Ungleichheits'-Beziehung* zwischen den mit noalias gekennzeichneten Argumenten darstellt ( restrict auf C-Ebene), die fĂŒr jeden Anruf unterschiedliche Werte haben können.

In diesem Fall wird jedoch zuerst die Funktion in die Schleife inlined, dann wird der Inline-Code beim Abrollen der Schleife dupliziert – und diese Duplizierung Ă€ndert die IDs nicht. Aus diesem Grund , denkt LLVM keiner der a 'kann alias s mit einem der b ' s, was falsch ist, weil a aus dem ersten und dritten Anrufe Aliase mit b vom zweiten Anruf (alle zeigen auf &mat[0] ).

Erstaunlicherweise kompiliert GCC dies auch falsch mit einer anderen Ausgabe. (Klang und GCC bei -O0 geben beide 7 10 ; Klirren bei -O3 gibt 7 7 ; GCC bei -O3 gibt 10 7 .) Äh, ich hoffe wirklich, dass ich es nicht getan habe Vermasseln Sie etwas und fĂŒgen Sie UB hinzu, aber ich verstehe nicht, wie...

* Es ist etwas komplizierter, aber in diesem Fall, da copy keine Zeigerarithmetik verwendet und auf beide Zeiger schreibt, ist die Ungleichung a != b notwendig und ausreichend, damit ein Aufruf nicht UB sein.

Alle 33 Kommentare

Ich arbeite noch daran, das zugrunde liegende Problem herauszufinden. Das interessante Ticket ist https://github.com/rust-lang/rust/issues/54462.

Verwenden der minimalen Reproduktion von @nagisa :


Minimierter Testfall ohne unsicheren Code (Achten Sie darauf, mit 1 Codegen-Einheit zu kompilieren!):

fn linidx(row: usize, col: usize) -> usize {
    row * 1 + col * 3
}

fn swappy() -> [f32; 12] {
    let mut mat = [1.0f32, 5.0, 9.0, 2.0, 6.0, 10.0, 3.0, 7.0, 11.0, 4.0, 8.0, 12.0];

    for i in 0..2 {
        for j in i+1..3 {
            if mat[linidx(j, 3)] > mat[linidx(i, 3)] {
                    for k in 0..4 {
                            let (x, rest) = mat.split_at_mut(linidx(i, k) + 1);
                            let a = x.last_mut().unwrap();
                            let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap();
                            ::std::mem::swap(a, b);
                    }
            }
        }
    }

    mat
}

fn main() {
    let mat = swappy();
    assert_eq!([9.0, 5.0, 1.0, 10.0, 6.0, 2.0, 11.0, 7.0, 3.0, 12.0, 8.0, 4.0], mat);
}

Ich konnte die OptimierungsdurchgÀnge von LLVM halbieren, um den Fehler zu finden.

Das AusfĂŒhren dieses Befehls fĂŒhrt zu einer funktionierenden ausfĂŒhrbaren Datei (ersetzen Sie bug.rs durch den Namen der Datei, in der Sie die Reproduktion gespeichert haben).

rustc -Z no-parallel-llvm -C codegen-units=1 -O -Z mutable-noalias=yes -C llvm-args=-opt-bisect-limit=2260 bug.rs

Beim AusfĂŒhren dieses Befehls fĂŒhrt dies zu einer fehlerhaften ausfĂŒhrbaren Datei (das `assert_eq`` schlĂ€gt fehl):

rustc -Z no-parallel-llvm -C codegen-units=1 -O -Z mutable-noalias=yes -C llvm-args=-opt-bisect-limit=2261 bug.rs

LLVM-Halbwertsausgabe

FĂŒr diese Datei entspricht die Optimierung 2261 Global Value Numbering on function (_ZN3bug6swappy17hdcc51d0e284ea38bE)

Die Halbierung von LLVM-Revisionen (unter Verwendung von llvmlab bisect) schrÀnkt sie auf r305936-r305938, vermutlich r305938, ein:

[BasicAA] Verwenden Sie MayAlias ​​anstelle von PartialAlias ​​fĂŒr den Fallback.

Beachten Sie, dass dies eine ziemlich alte Änderung vom Juni 2017 ist.

Bearbeiten: Wenn man sich die Commit-Beschreibung ansieht, scheint es wahrscheinlich, dass der Fehler vorher existierte, aber von BasicAA maskiert wurde, um zu verhindern, dass spĂ€tere Alias-PĂ€sse ausgefĂŒhrt werden, was durch den Commit behoben wurde. In diesem Fall wird das Aliasing zwischen zwei getelementptr Anweisungen ĂŒberprĂŒft,

Edit2: Außerdem verhindert die Übergabe von -enable-scoped-noalias=false als LLVM-Option die Fehlkompilierung. (Dies ist nicht ĂŒberraschend, da dies die Behandlung von Noalias insgesamt deaktiviert, aber nur fĂŒr den Fall, dass es hilft ...)

Wenn ich mir die IR vor GVN ansehe, habe ich das GefĂŒhl, dass die Hauptursache hier im Schleifenabwickeln liegen könnte, je nachdem, ob mein VerstĂ€ndnis der Funktionsweise von LLVM-Aliasing-Anmerkungen richtig ist.

Betrachten Sie einen Code wie

int *a, *b;
for (int i = 0; i < 4; i++) {
    a[i & 1] = b[i & 1];
}

wobei a[i & 1] und b[i & 1] innerhalb einer einzelnen Iteration keine Aliasnamen haben, aber a und b im Allgemeinen Aliasnamen haben können.

In LLVM IR wĂŒrde dies etwa so aussehen:

define void @test(i32* %addr1, i32* %addr2) {
start:
    br label %body

body:
    %i = phi i32 [ 0, %start ], [ %i2, %body ]
    %j = and i32 %i, 1
    %addr1i = getelementptr inbounds i32, i32* %addr1, i32 %j
    %addr2i = getelementptr inbounds i32, i32* %addr2, i32 %j

    %x = load i32, i32* %addr1i, !alias.scope !2
    store i32 %x, i32* %addr2i, !noalias !2

    %i2 = add i32 %i, 1
    %cmp = icmp slt i32 %i2, 4
    br i1 %cmp, label %body, label %end

end:
    ret void
}

!0 = !{!0}
!1 = !{!1, !0}
!2 = !{!1}

Wenn wir dies durch -loop-unroll laufen lassen, erhalten wir:

define void @test(i32* %addr1, i32* %addr2) {
start:
  br label %body

body:                                             ; preds = %start
  %x = load i32, i32* %addr1, !alias.scope !0
  store i32 %x, i32* %addr2, !noalias !0
  %addr1i.1 = getelementptr inbounds i32, i32* %addr1, i32 1
  %addr2i.1 = getelementptr inbounds i32, i32* %addr2, i32 1
  %x.1 = load i32, i32* %addr1i.1, !alias.scope !0
  store i32 %x.1, i32* %addr2i.1, !noalias !0
  %x.2 = load i32, i32* %addr1, !alias.scope !0
  store i32 %x.2, i32* %addr2, !noalias !0
  %addr1i.3 = getelementptr inbounds i32, i32* %addr1, i32 1
  %addr2i.3 = getelementptr inbounds i32, i32* %addr2, i32 1
  %x.3 = load i32, i32* %addr1i.3, !alias.scope !0
  store i32 %x.3, i32* %addr2i.3, !noalias !0
  ret void
}

!0 = !{!1}
!1 = distinct !{!1, !2}
!2 = distinct !{!2}

Beachten Sie, dass alle vier Kopien der Schleife Aliasing-Metadaten ĂŒber dieselbe Aliasing-DomĂ€ne verwenden. Anstatt Noalias innerhalb einer einzelnen Iteration zu sein, ist es Noalias fĂŒr die gesamte Funktion.

Schließlich gibt uns -scoped-noalias -gvn :

define void @test(i32* %addr1, i32* %addr2) {
start:
  %x = load i32, i32* %addr1, !alias.scope !0
  store i32 %x, i32* %addr2, !noalias !0
  %addr1i.1 = getelementptr inbounds i32, i32* %addr1, i32 1
  %addr2i.1 = getelementptr inbounds i32, i32* %addr2, i32 1
  %x.1 = load i32, i32* %addr1i.1, !alias.scope !0
  store i32 %x.1, i32* %addr2i.1, !noalias !0
  store i32 %x, i32* %addr2, !noalias !0
  store i32 %x.1, i32* %addr2i.1, !noalias !0
  ret void
}

!0 = !{!1}
!1 = distinct !{!1, !2}
!2 = distinct !{!2}

Und dies fĂŒhrt zu falschen Ergebnissen, wenn a = b + 1 .

Es ist möglich, dieses Problem von C aus mit dem folgenden Code zu reproduzieren:

#include "stdio.h"

void copy(int * restrict to, int * restrict from) {
    *to = *from;
}

void test(int *a, int *b) {
    for (int i = 0; i < 4; i++) {
        copy(&b[i & 1], &a[i & 1]);
    }
}

int main() {
    int ary[] = {0, 1, 2};
    test(&ary[1], &ary[0]);
    printf("%d %d %d\n", ary[0], ary[1], ary[2]);
    return 1;
}

Mit Clang 6.0 wird 2 2 2 bei -O0 und 1 2 2 bei -O3 . Ich bin mir nicht sicher, ob dieser Code unter der restrict Semantik in C zulÀssig ist, aber ich denke, er sollte unter der strengeren noalias Semantik von LLVM zulÀssig sein.

Ich habe es auf einen einfachen C-Testfall reduziert (bei -O3 und -O0 kompilieren und die Ausgabe vergleichen):

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

__attribute__((always_inline))
static inline void copy(int *restrict a, int *restrict b) {
    assert(a != b);
    *b = *a;
    *a = 7;
}

__attribute__((noinline))
void floppy(int mat[static 2], size_t idxs[static 3]) {
    for (int i = 0; i < 3; i++) {
        copy(&mat[i%2], &mat[idxs[i]]);
    }
}

int main() {
    int mat[3] = {10, 20};
    size_t idxs[3] = {1, 0, 1};
    floppy(mat, idxs);
    printf("%d %d\n", mat[0], mat[1]);
}

Beachten Sie, dass das Verhalten korrekt ist, wenn Sie restrict entfernen, das C-Äquivalent von noalias . Aber selbst dann passiert das assert(a != b) , was beweist, dass kein UB auftreten kann, weil es mit restrict .

Was passiert ist:

  1. copy() wird inline eingefĂŒgt, was in etwa zu folgendem Ergebnis fĂŒhrt:
for (int i = 0; i < 3; i++) {
    mat[idxs[i]] = mat[i%2]; mat[i%2] = 7;
}
  1. LLVM entrollt die Schleife:
mat[idxs[0]] = mat[0]; mat[0] = 7; /* from copy(&mat[0%2], &mat[idxs[0]]) */
mat[idxs[1]] = mat[1]; mat[1] = 7; /* from copy(&mat[1%2], &mat[idxs[1]]) */
mat[idxs[2]] = mat[0]; mat[0] = 7; /* from copy(&mat[2%2], &mat[idxs[2]]) */
  1. LLVM denkt, dass mat[0] kein Alias ​​mit mat[idxs[1]] oder mat[1] , ergo kann es nicht zwischen mat[0] = 7; und mat[idxs[2]] = mat[0]; geĂ€ndert worden sein, ergo ist es sicher fĂŒr globale Wertnummerierung, um letztere auf mat[idxs[2]] = 7; zu optimieren.

Aber mat[0] macht ein Alias ​​mit mat[idxs[1]] , weil idxs[1] == 0 . Und wir haben nicht versprochen, dass dies nicht der Fall ist, denn in der zweiten Iteration, wenn &mat[idxs[1]] an copy , ist das andere Argument &mat[1] . Warum denkt LLVM, dass dies nicht möglich ist?

Nun, es hat damit zu tun, wie copy eingebunden ist. Das Funktionsattribut noalias wird in !alias.scope und !noalias Metadaten fĂŒr die Lade- und Speicheranweisungen umgewandelt, wie:

  %8 = load i32, i32* %0, align 4, !tbaa !8, !alias.scope !10, !noalias !13
  store i32 %8, i32* %7, align 4, !tbaa !8, !alias.scope !13, !noalias !10
  store i32 7, i32* %0, align 4, !tbaa !8, !alias.scope !10, !noalias !13

Wenn eine Funktion mehrmals inline eingebunden ist, erhĂ€lt jede Kopie normalerweise ihre eigenen eindeutigen IDs fĂŒr alias.scope und noalias, was darauf hinweist, dass jeder Aufruf seine eigene 'Ungleichheits'-Beziehung* zwischen den mit noalias gekennzeichneten Argumenten darstellt ( restrict auf C-Ebene), die fĂŒr jeden Anruf unterschiedliche Werte haben können.

In diesem Fall wird jedoch zuerst die Funktion in die Schleife inlined, dann wird der Inline-Code beim Abrollen der Schleife dupliziert – und diese Duplizierung Ă€ndert die IDs nicht. Aus diesem Grund , denkt LLVM keiner der a 'kann alias s mit einem der b ' s, was falsch ist, weil a aus dem ersten und dritten Anrufe Aliase mit b vom zweiten Anruf (alle zeigen auf &mat[0] ).

Erstaunlicherweise kompiliert GCC dies auch falsch mit einer anderen Ausgabe. (Klang und GCC bei -O0 geben beide 7 10 ; Klirren bei -O3 gibt 7 7 ; GCC bei -O3 gibt 10 7 .) Äh, ich hoffe wirklich, dass ich es nicht getan habe Vermasseln Sie etwas und fĂŒgen Sie UB hinzu, aber ich verstehe nicht, wie...

* Es ist etwas komplizierter, aber in diesem Fall, da copy keine Zeigerarithmetik verwendet und auf beide Zeiger schreibt, ist die Ungleichung a != b notwendig und ausreichend, damit ein Aufruf nicht UB sein.

Heh, sieht aus, als wÀre ich mit @nikic gefahren, um die gleiche ErklÀrung zu finden. Ihr Testfall ist etwas schöner :)

Das ist ein wirklich tolles Timing ^^ Wir sind zu dem gleichen Schluss gekommen, mit fast dem gleichen reduzierten Testfall zur gleichen Zeit :)

Um dies zu beheben, muss wahrscheinlich auch in LoopUnrollPass etwas in der Art von https://github.com/llvm-mirror/llvm/blob/54d4881c352796b18bfe7314662a294754e3a752/lib/Transforms/Utils/InlineFunction.cpp#L801 durchgefĂŒhrt werden.

Ich habe einen LLVM-Fehlerbericht fĂŒr dieses Problem unter https://bugs.llvm.org/show_bug.cgi?id=39282 eingereicht

Und – nur der VollstĂ€ndigkeit halber – ich habe einen Fehlerbericht an GCC gesendet, da auch mein C-Testfall falsch kompiliert wurde: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87609

Triage: Wenn ich das richtig lese, wurde der LLVM-Fix akzeptiert (https://reviews.llvm.org/D9375). Ich bin mir nicht sicher, was das fĂŒr das ZusammenfĂŒhren mit LLVM bedeutet oder wann das passiert ist. jemand, der sich mit dem Revisionsprozess von LLVM besser auskennt, sollte ĂŒberprĂŒfen, ob das Problem jetzt behoben ist (und fĂŒr welche Versionen).

Es ist nicht zusammengefĂŒhrt, der ÜberprĂŒfungsprozess war etwas seltsam und die Person, die es genehmigt hat, ĂŒberprĂŒft keine Patches mehr.

Es gab einen Aufruf zum Testen mit dem Patch-Set "Full Restrict". Es wĂ€re wahrscheinlich wertvoll, wenn jemand versuchen wĂŒrde, Noalias in Rust auf einem llvm wieder zu aktivieren, auf das dieses Patch-Set angewendet wurde.

Ich bin bereit, das zu versuchen.
Ich habe Zugriff auf mĂ€ĂŸig leistungsstarke Server (48 HT-Kerne, 128 GB RAM) und denke, dass ich es schaffen kann, mit dem Patch alles richtig zu bauen.
Sobald ich eine funktionierende Toolchain habe, welche Kisten wĂŒrden Sie empfehlen, es auszuprobieren?

Ich habe alle rostspezifischen Commits auf dem Upstream-Master von Patch angewendet.
Hier ist der resultierende Zweig: https://github.com/PaulGrandperrin/llvm-project/tree/llvm-master-with-rustlang-patches-and-D69542
Ich werde jetzt versuchen, die Toolchain zu kompilieren und auszuprobieren

Stellen Sie zuerst sicher, dass Sie zurĂŒcksetzen: https://github.com/rust-lang/rust/pull/54639, damit Rust tatsĂ€chlich Noalias ausgibt.

Ein guter erster Versuch ist so etwas wie:

pub fn adds(a: &mut i32, b: &mut i32) {
    *a += *b;
    *a += *b;
}

und bestÀtigen Sie, dass es zu etwas kompiliert wird:

example::adds:
        mov     eax, dword ptr [rsi]
        add     eax, eax
        add     dword ptr [rdi], eax
        ret

und nicht

example::adds:
        mov     eax, dword ptr [rdi]
        add     eax, dword ptr [rsi]
        mov     dword ptr [rdi], eax
        add     eax, dword ptr [rsi]
        mov     dword ptr [rdi], eax
        ret

Stellen Sie als NĂ€chstes sicher, dass der Code von https://github.com/rust-lang/rust/issues/54462#issue -362850708 nicht mehr falsch kompiliert wird.

@jrmuizel Beachten Sie, dass #54639 @nagisas minimalen Reproduzierer fĂŒr #54462 als neuen Compiler-Test enthĂ€lt. Vielleicht ist eine vollstĂ€ndige Wiederherstellung nicht in Ordnung?

Ich denke nicht, dass es wichtig ist, es einzuschließen oder nicht, da es AFAIK nur darum geht, ein Standard-Flag zu Ă€ndern (das mit -Zmutable-noalias=yes ĂŒberschrieben werden kann) und ich die erwĂ€hnte Testdatei manuell kompilieren kann.

Nur damit Sie es wissen, ich versuche immer noch, LLVM zu erstellen, aber ab jetzt erhalte ich einen Kompilierungsfehler mit oder ohne angewendeten rostspezifischen Patches (dh: nur der llvm-Master des Upstreams + der Patch schlÀgt auch fehl):

In file included from /usr/include/c++/8/cmath:45,
                 from /opt/rust/src/llvm-project/llvm/include/llvm-c/DataTypes.h:28,
                 from /opt/rust/src/llvm-project/llvm/include/llvm/Support/DataTypes.h:16,
                 from /opt/rust/src/llvm-project/llvm/include/llvm/ADT/Hashing.h:47,
                 from /opt/rust/src/llvm-project/llvm/include/llvm/ADT/ArrayRef.h:12,
                 from /opt/rust/src/llvm-project/llvm/include/llvm/Transforms/Utils/NoAliasUtils.h:16,
                 from /opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:13:
/opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp: In function ‘void llvm::cloneNoAliasScopes(llvm::ArrayRef<llvm::MetadataAsValue*>, llvm::DenseMap<llvm::MDN
ode*, llvm::MDNode*>&, llvm::DenseMap<llvm::MetadataAsValue*, llvm::MetadataAsValue*>&, llvm::StringRef, llvm::LLVMContext&)’:
/opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:174:30: error: no matching function for call to ‘llvm::AliasScopeNode::AliasScopeNode(double)’
         llvm::AliasScopeNode SNAN(MD);
                              ^~~~
In file included from /opt/rust/src/llvm-project/llvm/include/llvm/IR/TrackingMDRef.h:16,
                 from /opt/rust/src/llvm-project/llvm/include/llvm/IR/DebugLoc.h:17,
                 from /opt/rust/src/llvm-project/llvm/include/llvm/IR/Instruction.h:21,
                 from /opt/rust/src/llvm-project/llvm/include/llvm/IR/BasicBlock.h:22,
                 from /opt/rust/src/llvm-project/llvm/include/llvm/IR/Instructions.h:27,
                 from /opt/rust/src/llvm-project/llvm/include/llvm/Transforms/Utils/NoAliasUtils.h:22,
                 from /opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:13:
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1446:12: note: candidate: ‘llvm::AliasScopeNode::AliasScopeNode(const llvm::MDNode*)’
   explicit AliasScopeNode(const MDNode *N) : Node(N) {}
            ^~~~~~~~~~~~~~
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1446:12: note:   no known conversion for argument 1 from ‘double’ to ‘const llvm::MDNode*’
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1445:3: note: candidate: ‘constexpr llvm::AliasScopeNode::AliasScopeNode()’
   AliasScopeNode() = default;
   ^~~~~~~~~~~~~~
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1445:3: note:   candidate expects 0 arguments, 1 provided
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1441:7: note: candidate: ‘constexpr llvm::AliasScopeNode::AliasScopeNode(const llvm::AliasScopeNode&)’
 class AliasScopeNode {
       ^~~~~~~~~~~~~~
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1441:7: note:   no known conversion for argument 1 from ‘double’ to ‘const llvm::AliasScopeNode&’
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1441:7: note: candidate: ‘constexpr llvm::AliasScopeNode::AliasScopeNode(llvm::AliasScopeNode&&)’
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1441:7: note:   no known conversion for argument 1 from ‘double’ to ‘llvm::AliasScopeNode&&’
/opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:177:31: error: request for member ‘getName’ in ‘__builtin_nans(((const char*)""))’, which is of non-class ty
pe ‘double’
         auto ScopeName = SNAN.getName();
                               ^~~~~~~
/opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:187:39: error: request for member ‘getDomain’ in ‘__builtin_nans(((const char*)""))’, which is of non-class
type ‘double’
             const_cast<MDNode *>(SNAN.getDomain()), Name);
                                       ^~~~~~~~~
[ 75%] Building CXX object lib/Target/Hexagon/CMakeFiles/LLVMHexagonCodeGen.dir/RDFCopy.cpp.o
make[2]: *** [lib/Transforms/Utils/CMakeFiles/LLVMTransformUtils.dir/build.make:635: lib/Transforms/Utils/CMakeFiles/LLVMTransformUtils.dir/NoAliasUtils.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....

Vielleicht ist der LLVM-Master bereits mit dem Patch nicht mehr synchron (was passieren könnte, wenn man bedenkt, wie groß der Patch ist und wie schnell sich der LLVM-Master bewegt) und Sie mĂŒssen gegen eine Ă€ltere Revision des LLVM-Masters bauen? Es wĂŒrde sich auf jeden Fall lohnen, den Patch-Autor diesbezĂŒglich anzupingen.

Genau das tue ich und versuche, eine Àltere Revision zu finden, die mit dem Patch erstellt wird :-)

Ich bin mir jetzt sicher, dass das Problem nicht an llvm/master liegt, sondern am Patch.
Der Ă€lteste Commit von llvm/master, der noch mit dem Patch kompatibel ist, ist https://github.com/llvm/llvm-project/commit/5b99c189b3bfc0faa157f7ca39652c0bb8c315a7 aber selbst so weit zurĂŒck kann der Patch nicht kompiliert werden.
Ich bin zu mĂŒde und faul, um jetzt zu versuchen, C++ zu verstehen, ich werde es morgen noch einmal versuchen.
Kann sich in der Zwischenzeit jemand an den Autor des Patches wenden, um um Hilfe zu bitten?

Ich glaube nicht, dass Sie Master-LLVM mit Rust problemlos verwenden können (nachdem Sie es tatsĂ€chlich erstellt haben), ohne rustllvm zu patchen. AFAIK unterstĂŒtzt derzeit nur die Releases 6-9.

@ mati865 Ich habe zuerst versucht, den Patch auf die llvm-9-Gabel von Rust aufzutragen, aber es war auch sehr viel nicht trivial ...

Der Patch basiert anscheinend auf llvm/ llvm-project@82d3ba87d06f9e2abc6e27d8799587d433c56630. Hilft es Ihnen, wenn Sie sich darĂŒber hinaus bewerben?

@jrmuizel danke das werde ich versuchen!
In der Zwischenzeit konnte ich rustllvm erfolgreich anpassen, um mit llvm master zu bauen.

Ping @PaulGrandperrin , irgendwelche Updates?

https://reviews.llvm.org/D68484

Was ist realistisch betrachtet die geschĂ€tzte Zeitachse und die Gesamtwahrscheinlichkeit, dass dieser Patch jemals zusammengefĂŒhrt wird, wenn man seine GrĂ¶ĂŸe bedenkt?

@MSxDOS Sie möchten die LLVM-Entwickler fragen. Im Allgemeinen wĂŒrde ich erwarten, dass die GrĂ¶ĂŸe eines Patches weniger wichtig ist als der Wunsch der Besitzer, ihn zusammenzufĂŒhren, also stellt sich die Frage, wie viel LLVM will, dass er landet.

Hier ist der neueste Status, den ich gesehen habe: https://reviews.llvm.org/D69542#1836439

Ich gehe davon aus, dass es irgendwann nicht mehr relevant sein wird, wenn https://github.com/bytecodealliance/cranelift~~ https://github.com/bjorn3/rustc_codegen_cranelift funktioniert?

@leeoniya , es gibt keinen kurzfristigen Plan, Kranlift fĂŒr Opt-Builds zu verwenden. Cranlift hat nicht viele Optimierungsarbeiten, die erforderlich wĂ€ren, um dies zu ermöglichen.

Ich war ĂŒberrascht, wie konservativ der Compiler in Bezug auf die Annahme ist, dass es ohne diese Option Aliasing geben könnte. Beispielsweise:

fn baz(s: &mut S) {
    if s.y < 10 {
        s.x = foo();
    }

    if s.y < 5 {
        s.x = foo();
    }
}

Da es auf die Strukturmember ĂŒber ein &mut zugreift, wird davon ausgegangen, dass s.x und s.y Aliasnamen haben können, sodass fĂŒr s.y zwei Speicherzugriffe anstelle von einem erforderlich sind. Das ist wirklich bedauerlich, wenn man bedenkt, wie oft Member-Lese-/SchreibvorgĂ€nge ĂŒber &mut in einem typischen Programm verschachtelt werden mĂŒssen.

Bearbeiten: Basierend auf einigen Tests scheint dies nicht alle derartigen Lese-/SchreibvorgĂ€nge zu beeinflussen, was nicht verwunderlich ist, da dies wahrscheinlich die Leistung beeintrĂ€chtigen wĂŒrde, wenn dies der Fall wĂ€re. Die Verwendung von -Z mutable-noalias behebt jedoch den doppelten Speicherzugriff im obigen Beispiel, so dass einige FĂ€lle kaputt gehen können.

@PaulGrandperrin es gibt eine neue Version dieses Patches unter https://reviews.llvm.org/D69542 basierend auf llvm@9fb46a452d4e5666828c95610ceac8dcd9e4ce16. Sind Sie bereit, es wieder zum Laufen zu bringen?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen