Наскільки я знаю, псевдонім посилання / вказівника може перешкоджати можливості компілятора генерувати оптимізований код, оскільки вони повинні забезпечувати, щоб згенерований бінарний файл поводився правильно у випадку, коли два посилання / покажчики справді псевдоніми. Наприклад, у наведеному нижче коді С
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 + *b
b* + *b
2: 01 c0 add %eax,%eax
*b
4: