Cor*_*lks 26 rust llvm-codegen
以下指针别名示例:
pub unsafe fn f(a: *mut i32, b: *mut i32, x: *const i32) {
*a = *x;
*b = *x;
}
Run Code Online (Sandbox Code Playgroud)
编译成以下程序集(with -C opt-level=s):
example::f:
push rbp
mov rbp, rsp
mov eax, dword ptr [rdx]
mov dword ptr [rdi], eax
mov eax, dword ptr [rdx]
mov dword ptr [rsi], eax
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
请注意,x它被解除引用两次.LLVM没有将其视为noalias.我的第一个想法是避免在赋值中使用指针,而是使用安全引用(因为那些" 遵循LLVM的作用域noalias模型 ")来给优化器提示:
pub fn g(a: *mut i32, b: *mut i32, x: *const i32) {
let safe_a = unsafe { &mut *a };
let safe_b = unsafe { &mut *b };
let safe_x = unsafe { &*x };
*safe_a = *safe_x;
*safe_b = *safe_x;
}
Run Code Online (Sandbox Code Playgroud)
但是,唉,这会产生完全相同的结果.safe_x仍被解除引用两次.
我知道这个示例代码是愚蠢的.参数可以很容易地更改为&i32/ &mut i32,或者我可以只取消引用x一次并将其存储在用于赋值的临时中.这里的代码只是一个超级简单的别名测试,我对我的问题所要求的更广泛的图片感兴趣.
有,将安全引用包装在函数或闭包中:
pub unsafe fn f(a: *mut i32, b: *mut i32, x: *const i32) {
(|safe_a: &mut i32, safe_b: &mut i32, safe_x: &i32| {
*safe_a = *safe_x;
*safe_b = *safe_x;
})(&mut *a, &mut *b, &*x)
}
Run Code Online (Sandbox Code Playgroud)
这会产生所需的非锯齿行为:
example::f:
movl (%rdx), %eax
movl %eax, (%rdi)
movl %eax, (%rsi)
retq
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
417 次 |
| 最近记录: |