Soweit ich weiß, kann Referenz- / Zeiger-Aliasing die Fähigkeit des Compilers beeinträchtigen, optimierten Code zu generieren, da sie sicherstellen müssen, dass sich die generierte Binärdatei korrekt verhält, wenn die beiden Referenzen / Zeiger tatsächlich Alias sind. Zum Beispiel im folgenden C-Code:
void adds(int *a, int *b) {
*a += *b;
*a += *b;
}
Wenn es clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
mit dem -O3
Flag kompiliert wird , wird es ausgegeben
0000000000000000 <adds>:
0: 8b 07 mov (%rdi),%eax
2: 03 06 add (%rsi),%eax
4: 89 07 mov %eax,(%rdi) # The first time
6: 03 06 add (%rsi),%eax
8: 89 07 mov %eax,(%rdi) # The second time
a: c3 retq
Hier speichert der Code (%rdi)
zweimal in case int *a
und int *b
alias.
Wenn wir dem Compiler ausdrücklich mitteilen, dass diese beiden Zeiger keinen Alias mit dem restrict
Schlüsselwort haben können:
void adds(int * restrict a, int * restrict b) {
*a += *b;
*a += *b;
}
Dann wird Clang eine optimierte Version des Binärcodes ausgeben:
0000000000000000 <adds>:
0: 8b 06 mov (%rsi),%eax
2: 01 c0 add %eax,%eax
4: 01 07 add %eax,(%rdi)
6: c3 retq
Da Rust (außer in unsicherem Code) sicherstellt, dass zwei veränderbare Referenzen keinen Alias haben können, würde ich denken, dass der Compiler in der Lage sein sollte, die optimierte Version des Codes auszugeben.
Als ich mit dem Code testen unten und kompilieren Sie es mit rustc 1.35.0
mit -C opt-level=3 --emit obj
,
#![crate_type = "staticlib"]
#[no_mangle]
fn adds(a: &mut i32, b: &mut i32) {
*a += *b;
*a += *b;
}
es erzeugt:
0000000000000000 <adds>:
0: 8b 07 mov (%rdi),%eax
2: 03 06 add (%rsi),%eax
4: 89 07 mov %eax,(%rdi)
6: 03 06 add (%rsi),%eax
8: 89 07 mov %eax,(%rdi)
a: c3 retq
Dies nutzt die Garantie nicht aus a
und b
kann nicht alias.
Liegt das daran, dass sich der aktuelle Rust-Compiler noch in der Entwicklung befindet und noch keine Alias-Analyse für die Optimierung integriert hat?
Liegt das daran, dass es immer noch eine Chance gibt a
und b
Alias auch in sicherem Rust sein könnte?
unsafe
Aliasing veränderlicher Verweise auch im Code nicht zulässig ist und zu undefiniertem Verhalten führt. Sie können Aliasing-Rohzeiger verwenden, aber mit unsafe
Code können Sie die Rust-Standardregeln nicht ignorieren. Es ist nur ein weit verbreitetes Missverständnis und daher erwähnenswert.
+=
Operationen im Körper von adds
als neu interpretiert werden können *a = *a + *b + *b
. Wenn die Zeiger keinen Alias haben, können Sie sogar b* + *b
in der zweiten ASM-Liste sehen, was sie bedeuten : 2: 01 c0 add %eax,%eax
. Wenn sie jedoch einen Alias verwenden, können sie dies nicht, da er *b
zum zweiten Mal einen anderen Wert enthält als beim ersten Mal (den Wert, den Sie online 4:
in der ersten ASM-Liste speichern ).