Per quanto ne so, l'aliasing di riferimento / puntatore può ostacolare la capacità del compilatore di generare codice ottimizzato, dal momento che devono assicurarsi che il binario generato si comporti correttamente nel caso in cui i due riferimenti / puntatori siano effettivamente alias. Ad esempio, nel seguente codice C,
void adds(int *a, int *b) {
*a += *b;
*a += *b;
}
quando compilato da clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)con la -O3bandiera, emette
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
Qui il codice viene archiviato (%rdi)due volte nel caso int *ae int *balias.
Quando diciamo esplicitamente al compilatore che questi due puntatori non possono alias con la restrictparola chiave:
void adds(int * restrict a, int * restrict b) {
*a += *b;
*a += *b;
}
Quindi Clang emetterà una versione più ottimizzata del codice binario:
0000000000000000 <adds>:
0: 8b 06 mov (%rsi),%eax
2: 01 c0 add %eax,%eax
4: 01 07 add %eax,(%rdi)
6: c3 retq
Dal momento che Rust si assicura (tranne che nel codice non sicuro) che due riferimenti mutabili non possono essere alias, penso che il compilatore dovrebbe essere in grado di emettere la versione più ottimizzata del codice.
Quando eseguo il test con il codice seguente e lo compilo con rustc 1.35.0con -C opt-level=3 --emit obj,
#![crate_type = "staticlib"]
#[no_mangle]
fn adds(a: &mut i32, b: &mut i32) {
*a += *b;
*a += *b;
}
genera:
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
Questo non sfrutta la garanzia che ae bnon può alias.
Questo perché l'attuale compilatore Rust è ancora in fase di sviluppo e non ha ancora incorporato l'analisi degli alias per eseguire l'ottimizzazione?
È perché c'è ancora una possibilità che ae balias, anche in Rust sicuro?
unsafecodice, i riferimenti mutabili alias non sono consentiti e comportano un comportamento indefinito. È possibile avere alias di puntatori unsafenon elaborati, ma il codice non consente in realtà di ignorare le regole standard di Rust. È solo un malinteso comune e quindi vale la pena sottolineare.
+=operazioni nel corpo di addspossano essere reinterpretate come *a = *a + *b + *b. Se i puntatori non lo fanno alias, si può, si può anche vedere ciò che equivale a b* + *bnel secondo asm messa in vendita: 2: 01 c0 add %eax,%eax. Ma se fanno alias, non possono, perché quando aggiungi *bper la seconda volta, conterrà un valore diverso rispetto alla prima volta (quello che memorizzi sulla riga 4:del primo elenco asm).