Наскільки я знаю, псевдонім посилання / вказівника може перешкоджати можливості компілятора генерувати оптимізований код, оскільки вони повинні забезпечувати, щоб згенерований бінарний файл поводився правильно у випадку, коли два посилання / покажчики справді псевдоніми. Наприклад, у наведеному нижче коді С
void adds(int *a, int *b) {
*a += *b;
*a += *b;
}
при компіляції clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)з -O3прапором він випромінює
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
Тут код зберігається (%rdi)двічі у випадку int *aі int *bпсевдоніму.
Коли ми чітко повідомляємо компілятору, що ці два покажчики не можуть мати псевдонім з restrictключовим словом:
void adds(int * restrict a, int * restrict b) {
*a += *b;
*a += *b;
}
Тоді Кланг випустить більш оптимізовану версію двійкового коду:
0000000000000000 <adds>:
0: 8b 06 mov (%rsi),%eax
2: 01 c0 add %eax,%eax
4: 01 07 add %eax,(%rdi)
6: c3 retq
Оскільки Руст переконує (за винятком небезпечного коду), що дві змінні посилання не можуть мати псевдонім, я думаю, що компілятор повинен мати можливість видавати більш оптимізовану версію коду.
Коли я тестую з кодом нижче і компілюю його rustc 1.35.0з -C opt-level=3 --emit obj,
#![crate_type = "staticlib"]
#[no_mangle]
fn adds(a: &mut i32, b: &mut i32) {
*a += *b;
*a += *b;
}
він генерує:
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
Це не скористатися гарантією того, що aі bне може псевдонім.
Це тому, що поточний компілятор Rust все ще знаходиться в розробці і ще не включив псевдонімічний аналіз для оптимізації?
Це тому, що все ж є ймовірність, що могла б aі bпсевдонім, навіть у безпечній Іржі?
unsafeкоді дозволені змінні посилання не дозволені і призводять до невизначеної поведінки. Ви можете мати прізвище необроблених покажчиків, але unsafeкод насправді не дозволяє вам ігнорувати стандартні правила Rust. Це просто поширене неправильне уявлення і, таким чином, варто звернути увагу.
+=операції в тілі . Якщо покажчики НЕ псевдонім, вони можуть, ви навіть можете побачити , що становить у другому ассемблерного лістингу: . Але якщо вони роблять псевдонім, вони не можуть, оскільки до того часу, коли ви додасте його вдруге, воно буде містити інше значення, ніж перший раз (те, яке ви зберігаєте в рядку першого списку asm). adds*a = *a + *b + *bb* + *b2: 01 c0 add %eax,%eax*b4: