Pour autant que je sache, l'alias de référence/pointeur peut entraver la capacité du compilateur à générer du code optimisé, car ils doivent garantir que le binaire généré se comporte correctement dans le cas où les deux références/pointeurs sont effectivement des alias. Par exemple, dans le code C suivant,
void adds(int *a, int *b) {
*a += *b;
*a += *b;
}
lorsqu'il est compilé par clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
avec le drapeau -O3
, il émet
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
Ici, le code est stocké deux fois dans (%rdi)
Au cas où int *a
Et int *b
Alias.
Lorsque nous disons explicitement au compilateur que ces deux pointeurs ne peuvent pas alias avec le mot clé restrict
:
void adds(int * restrict a, int * restrict b) {
*a += *b;
*a += *b;
}
Ensuite, Clang émettra une version plus optimisée du code binaire:
0000000000000000 <adds>:
0: 8b 06 mov (%rsi),%eax
2: 01 c0 add %eax,%eax
4: 01 07 add %eax,(%rdi)
6: c3 retq
Puisque Rust s'assure (sauf dans le code non sûr) que deux références mutables ne peuvent pas être alias, je pense que le compilateur devrait pouvoir émettre la version la plus optimisée du code.
Lorsque je teste avec le code ci-dessous et que je le compile avec rustc 1.35.0
Avec -C opt-level=3 --emit obj
,
#![crate_type = "staticlib"]
#[no_mangle]
fn adds(a: &mut i32, b: &mut i32) {
*a += *b;
*a += *b;
}
il génère:
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
Cela ne profite pas de la garantie que a
et b
ne peuvent pas être alias.
Est-ce parce que le compilateur Rust Rust est toujours en développement et n'a pas encore incorporé d'analyse d'alias pour faire l'optimisation?
Est-ce parce qu'il y a encore une chance que a
et b
puissent alias, même dans Rust sécurisé?
Rust à l'origine did active l'attribut noalias
de LLVM, mais cela a provoqué une erreur de compilation . Lorsque toutes les versions LLVM prises en charge ne compilent plus le code, il sera réactivé .
Si vous ajoutez -Zmutable-noalias=yes
aux options du compilateur, vous obtenez l'assembly attendu:
adds:
mov eax, dword ptr [rsi]
add eax, eax
add dword ptr [rdi], eax
ret
Autrement dit, Rust mettez l'équivalent du mot-clé restrict
de C partout , beaucoup plus répandu que tout autre programme C habituel. Cela a exercé des cas d'angle de LLVM plus qu'il ne pouvait gérer correctement. Il s'avère que les programmeurs C et C++ n'utilisent tout simplement pas restrict
aussi souvent que &mut
est utilisé dans Rust.
Cela s'est produit plusieurs fois .
noalias
activénoalias
désactivénoalias
activénoalias
désactivéCas actuel
Cas précédent
Autre