์ด ๋ฌธ์ ๋ LLVM์ ๋ฒ๊ทธ๋ก ์ธํด https://github.com/rust-lang/rust/pull/54639 ์ ๋์
๋ -Zmutable-alias=no
๊ธฐ๋ณธ๊ฐ์ ์คํ ์ทจ์๋ฅผ ์ถ์ ํฉ๋๋ค. cc @nagisa
( ๋ฐ์๋ทฐ? )
๋๋ ์ฌ์ ํ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ ๋ฅผ ํ์ ํ๊ธฐ ์ํด ๋ ธ๋ ฅํ๊ณ ์์ต๋๋ค. ํฅ๋ฏธ๋ก์ด ํฐ์ผ์ https://github.com/rust-lang/rust/issues/54462์ ๋๋ค.
@nagisa ์ ์ต์ โโ์ฌ์์ฐ ์ฌ์ฉ:
์์ ํ์ง ์์ ์ฝ๋๊ฐ ์๋ ์ต์ํ๋ ํ
์คํธ ์ผ์ด์ค(1 codegen ๋จ์๋ก ์ปดํ์ผํด์ผ ํฉ๋๋ค!):
fn linidx(row: usize, col: usize) -> usize {
row * 1 + col * 3
}
fn swappy() -> [f32; 12] {
let mut mat = [1.0f32, 5.0, 9.0, 2.0, 6.0, 10.0, 3.0, 7.0, 11.0, 4.0, 8.0, 12.0];
for i in 0..2 {
for j in i+1..3 {
if mat[linidx(j, 3)] > mat[linidx(i, 3)] {
for k in 0..4 {
let (x, rest) = mat.split_at_mut(linidx(i, k) + 1);
let a = x.last_mut().unwrap();
let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap();
::std::mem::swap(a, b);
}
}
}
}
mat
}
fn main() {
let mat = swappy();
assert_eq!([9.0, 5.0, 1.0, 10.0, 6.0, 2.0, 11.0, 7.0, 3.0, 12.0, 8.0, 4.0], mat);
}
LLVM์ ์ต์ ํ ํจ์ค๋ฅผ ์ด๋ฑ๋ถํ์ฌ ์ค๋ฅ๋ฅผ ์ผ์ผํค๋ ํจ์ค๋ฅผ ์ฐพ์ ์ ์์์ต๋๋ค.
์ด ๋ช
๋ น์ ์คํํ๋ฉด ์คํ ๊ฐ๋ฅํ ํ์ผ์ด ์์ฑ๋ฉ๋๋ค( bug.rs
๋ฅผ ์ฌ์์ฐ์ ์ ์ฅํ ํ์ผ ์ด๋ฆ์ผ๋ก ๋์ฒด).
rustc -Z no-parallel-llvm -C codegen-units=1 -O -Z mutable-noalias=yes -C llvm-args=-opt-bisect-limit=2260 bug.rs
์ด ๋ช ๋ น์ ์คํํ๋ ๋์ ์คํ ํ์ผ์ด ์์๋ฉ๋๋ค(`assert_eq`` ์คํจ).
rustc -Z no-parallel-llvm -C codegen-units=1 -O -Z mutable-noalias=yes -C llvm-args=-opt-bisect-limit=2261 bug.rs
์ด ํ์ผ์ ๊ฒฝ์ฐ, ์ต์ ํ 2261
์ ํด๋นํ๋ Global Value Numbering on function (_ZN3bug6swappy17hdcc51d0e284ea38bE)
LLVM ๊ฐ์ ์ ์ด๋ฑ๋ถํ๋ฉด(llvmlab bisect ์ฌ์ฉ) r305936-r305938(์๋ง๋ r305938)๋ก ์ขํ๋๋ค.
[BasicAA] ๋์ฒด๋ฅผ ์ํด PartialAlias โโ๋์ MayAlias๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ด๊ฒ์ 2017๋ 6์๋ถํฐ ๊ฝค ์ค๋๋ ๋ณ๊ฒฝ ์ฌํญ์ ๋๋ค.
ํธ์ง: ์ปค๋ฐ ์ค๋ช
์ ๋ณด๋ฉด ๋ฒ๊ทธ๊ฐ ๊ทธ ์ด์ ์ ์กด์ฌํ์ ๊ฐ๋ฅ์ฑ์ด ์์ง๋ง BasicAA์ ์ํด ๋ง์คํน๋์ด ์ดํ ๋ณ์นญ ํจ์ค๊ฐ ์คํ๋์ง ์์ ์ปค๋ฐ์ด ์์ ๋์์ต๋๋ค. ์ด ๊ฒฝ์ฐ์๋ ์ปดํ์ผ๋ฌ๊ฐ ๋์ผํ ๊ธฐ๋ณธ ์ฃผ์๋ฅผ ๊ฐ์ง๊ณ ์์ง๋ง ์คํ์
์ ์์ง ๋ชปํ๋ getelementptr
๋ช
๋ น์ด ์ ๊ฐ์ ์จ๋ฆฌ์ด์ฑ์ ํ์ธํ๋ ๊ฒ์ด ํฌํจ๋ฉ๋๋ค.
Edit2: ๋ํ -enable-scoped-noalias=false
๋ฅผ LLVM ์ต์
์ผ๋ก ์ ๋ฌํ๋ฉด ์๋ชป๋ ์ปดํ์ผ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค. (์ด๊ฒ์ noalias ์ฒ๋ฆฌ๋ฅผ ์์ ํ ๋นํ์ฑํํ๋ฏ๋ก ๋๋ผ์ด ์ผ์ด ์๋์ง๋ง ๋์์ด๋๋ ๊ฒฝ์ฐ๋ฅผ ๋๋นํ์ฌ ...)
GVN ์ด์ IR์ ์ดํด๋ณด๋ฉด LLVM ์จ๋ฆฌ์ด์ฑ ์ฃผ์์ด ์๋ํ๋ ๋ฐฉ์์ ๋ํ ๋์ ์ดํด๊ฐ ์ฌ๋ฐ๋ฅธ์ง ์ฌ๋ถ์ ๋ฐ๋ผ ์ฌ๊ธฐ์ ๊ทผ๋ณธ ์์ธ์ด ๋ฃจํ ํด์ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ๊ณ ๋ คํ์ญ์์ค.
int *a, *b;
for (int i = 0; i < 4; i++) {
a[i & 1] = b[i & 1];
}
์ฌ๊ธฐ์ a[i & 1]
๋ฐ b[i & 1]
๋ ๋จ์ผ ๋ฐ๋ณต ๋ด์์ ๋ณ์นญ์ ์ง์ ํ์ง ์์ง๋ง a
๋ฐ b
๋ ์ผ๋ฐ์ ์ผ๋ก ๋ณ์นญ์ ์ง์ ํ ์ ์์ต๋๋ค.
LLVM IR์์๋ ๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋๋ค.
define void @test(i32* %addr1, i32* %addr2) {
start:
br label %body
body:
%i = phi i32 [ 0, %start ], [ %i2, %body ]
%j = and i32 %i, 1
%addr1i = getelementptr inbounds i32, i32* %addr1, i32 %j
%addr2i = getelementptr inbounds i32, i32* %addr2, i32 %j
%x = load i32, i32* %addr1i, !alias.scope !2
store i32 %x, i32* %addr2i, !noalias !2
%i2 = add i32 %i, 1
%cmp = icmp slt i32 %i2, 4
br i1 %cmp, label %body, label %end
end:
ret void
}
!0 = !{!0}
!1 = !{!1, !0}
!2 = !{!1}
-loop-unroll
ํตํด ์ด๊ฒ์ ์คํํ๋ฉด ๋ค์์ ์ป์ต๋๋ค.
define void @test(i32* %addr1, i32* %addr2) {
start:
br label %body
body: ; preds = %start
%x = load i32, i32* %addr1, !alias.scope !0
store i32 %x, i32* %addr2, !noalias !0
%addr1i.1 = getelementptr inbounds i32, i32* %addr1, i32 1
%addr2i.1 = getelementptr inbounds i32, i32* %addr2, i32 1
%x.1 = load i32, i32* %addr1i.1, !alias.scope !0
store i32 %x.1, i32* %addr2i.1, !noalias !0
%x.2 = load i32, i32* %addr1, !alias.scope !0
store i32 %x.2, i32* %addr2, !noalias !0
%addr1i.3 = getelementptr inbounds i32, i32* %addr1, i32 1
%addr2i.3 = getelementptr inbounds i32, i32* %addr2, i32 1
%x.3 = load i32, i32* %addr1i.3, !alias.scope !0
store i32 %x.3, i32* %addr2i.3, !noalias !0
ret void
}
!0 = !{!1}
!1 = distinct !{!1, !2}
!2 = distinct !{!2}
๋ฃจํ์ 4๊ฐ ์ฌ๋ณธ ๋ชจ๋๊ฐ ๋์ผํ ์จ๋ฆฌ์ด์ฑ ๋๋ฉ์ธ์์ ์จ๋ฆฌ์ด์ฑ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ ์ํ์ญ์์ค. ๋จ์ผ ๋ฐ๋ณต ๋ด์์ noalias๊ฐ ๋๋ ๋์ ์ ์ฒด ๊ธฐ๋ฅ์ ๊ฑธ์ณ noalias์ ๋๋ค.
๋ง์ง๋ง์ผ๋ก -scoped-noalias -gvn
๋ ๋ค์์ ์ ๊ณตํฉ๋๋ค.
define void @test(i32* %addr1, i32* %addr2) {
start:
%x = load i32, i32* %addr1, !alias.scope !0
store i32 %x, i32* %addr2, !noalias !0
%addr1i.1 = getelementptr inbounds i32, i32* %addr1, i32 1
%addr2i.1 = getelementptr inbounds i32, i32* %addr2, i32 1
%x.1 = load i32, i32* %addr1i.1, !alias.scope !0
store i32 %x.1, i32* %addr2i.1, !noalias !0
store i32 %x, i32* %addr2, !noalias !0
store i32 %x.1, i32* %addr2i.1, !noalias !0
ret void
}
!0 = !{!1}
!1 = distinct !{!1, !2}
!2 = distinct !{!2}
a = b + 1
๊ฒฝ์ฐ ์๋ชป๋ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ํฉ๋๋ค.
๋ค์ ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ C์์ ์ด ๋ฌธ์ ๋ฅผ ์ฌํํ ์ ์์ต๋๋ค.
#include "stdio.h"
void copy(int * restrict to, int * restrict from) {
*to = *from;
}
void test(int *a, int *b) {
for (int i = 0; i < 4; i++) {
copy(&b[i & 1], &a[i & 1]);
}
}
int main() {
int ary[] = {0, 1, 2};
test(&ary[1], &ary[0]);
printf("%d %d %d\n", ary[0], ary[1], ary[2]);
return 1;
}
Clang 6.0์์๋ 2 2 2
at -O0
๋ฐ 1 2 2
at -O3
๋ฉ๋๋ค. ์ด ์ฝ๋๊ฐ C์ restrict
์๋ฏธ ์ฒด๊ณ์์ ํฉ๋ฒ์ ์ธ์ง ํ์คํ์ง ์์ง๋ง LLVM์ ๋ ์๊ฒฉํ noalias
์๋ฏธ ์ฒด๊ณ์์๋ ํฉ๋ฒ์ ์ด์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ฐ๋จํ C ํ ์คํธ ์ผ์ด์ค๋ก ์ถ์ํ์ต๋๋ค(-O3 ๋ฐ -O0์์ ์ปดํ์ผํ๊ณ ์ถ๋ ฅ ๋น๊ต).
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
__attribute__((always_inline))
static inline void copy(int *restrict a, int *restrict b) {
assert(a != b);
*b = *a;
*a = 7;
}
__attribute__((noinline))
void floppy(int mat[static 2], size_t idxs[static 3]) {
for (int i = 0; i < 3; i++) {
copy(&mat[i%2], &mat[idxs[i]]);
}
}
int main() {
int mat[3] = {10, 20};
size_t idxs[3] = {1, 0, 1};
floppy(mat, idxs);
printf("%d %d\n", mat[0], mat[1]);
}
์ฐธ๊ณ ์ ๊ฑฐํ๋ฉด ๊ฒ์ restrict
์ ๋๋ฑํ C noalias
, ๋์์ ์ฌ๋ฐ๋ฅธ ๊ฒ์
๋๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ assert(a != b)
๊ฐ ํต๊ณผํ์ฌ restrict
๋ก ํธ์ถํ์ฌ UB๊ฐ ๋ฐ์ํ ์ ์์์ ์ฆ๋ช
ํฉ๋๋ค.
๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง :
for (int i = 0; i < 3; i++) {
mat[idxs[i]] = mat[i%2]; mat[i%2] = 7;
}
mat[idxs[0]] = mat[0]; mat[0] = 7; /* from copy(&mat[0%2], &mat[idxs[0]]) */
mat[idxs[1]] = mat[1]; mat[1] = 7; /* from copy(&mat[1%2], &mat[idxs[1]]) */
mat[idxs[2]] = mat[0]; mat[0] = 7; /* from copy(&mat[2%2], &mat[idxs[2]]) */
mat[0]
๊ฐ mat[idxs[1]]
๋๋ mat[1]
์ ๋ณ์นญ์ ์ง์ ํ ์ ์๋ค๊ณ ์๊ฐํ๋ฏ๋ก mat[0] = 7;
์ mat[idxs[2]] = mat[0];
์ฌ์ด์์ ๋ณ๊ฒฝํ ์ ์์ผ๋ฏ๋ก ์์ ํฉ๋๋ค. ํ์๋ฅผ mat[idxs[2]] = 7;
๋ก ์ต์ ํํ๊ธฐ ์ํ ์ ์ญ ๊ฐ ๋ฒํธ ๋งค๊ธฐ๊ธฐ .ํ์ง๋ง mat[0]
๋ mat[idxs[1]]
๋ณ์นญ์ ์ฌ์ฉํฉ๋๋ค. ์๋ํ๋ฉด idxs[1] == 0
์ด๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ &mat[idxs[1]]
๊ฐ copy
์ ๋ฌ๋๋ ๋ ๋ฒ์งธ ๋ฐ๋ณต์์ ๋ค๋ฅธ ์ธ์๊ฐ &mat[1]
์ด๊ธฐ ๋๋ฌธ์ ๊ทธ๋ ๊ฒ ํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ์ฝ์ํ์ง ์์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด ์ LLVM์ ๊ทธ๋ ๊ฒ ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๊น?
๊ธ์, ๊ทธ๊ฒ์ copy
๊ฐ ์ธ๋ผ์ธ๋๋ ๋ฐฉ์๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค. noalias
ํจ์ ์์ฑ์ ๋ค์๊ณผ ๊ฐ์ด ๋ก๋ ๋ฐ ์ ์ฅ ์ง์นจ์์ !alias.scope
๋ฐ !noalias
๋ฉํ๋ฐ์ดํฐ๋ก ๋ฐ๋๋๋ค.
%8 = load i32, i32* %0, align 4, !tbaa !8, !alias.scope !10, !noalias !13
store i32 %8, i32* %7, align 4, !tbaa !8, !alias.scope !13, !noalias !10
store i32 7, i32* %0, align 4, !tbaa !8, !alias.scope !10, !noalias !13
์ผ๋ฐ์ ์ผ๋ก ํจ์๊ฐ ์ฌ๋ฌ ๋ฒ ์ธ๋ผ์ธ๋๋ ๊ฒฝ์ฐ ๊ฐ ๋ณต์ฌ๋ณธ์ alias.scope ๋ฐ noalias์ ๋ํด ๊ณ ์ ํ ID๋ฅผ ๊ฐ์ ธ์ค๋ฉฐ, ์ด๋ ๊ฐ ํธ์ถ์ด noalias
( restrict
at C level), ์ด๋ ๊ฐ ํธ์ถ์ ๋ํด ๋ค๋ฅธ ๊ฐ์ ๊ฐ์ง ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ด ๊ฒฝ์ฐ ๋จผ์ ํจ์๊ฐ ๋ฃจํ์ ์ธ๋ผ์ธ๋ ๋ค์ ๋ฃจํ๊ฐ ํด์ ๋ ๋ ์ธ๋ผ์ธ๋ ์ฝ๋๊ฐ ๋ณต์ ๋๋ฉฐ ์ด ์ค๋ณต์ผ๋ก ID๊ฐ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. ์ด๊ฒ ๋๋ฌธ์, LLVM์ ์ ํ ์๊ฐํ์ง a
'์ ์ด๋ค๊ณผ์ ์บ ๋ณ์นญ์ b
, ๊ฑฐ์ง์,'๋๋ฌธ์ a
์ฒซ ๋ฒ์งธ์ ์ธ ๋ฒ์งธ ํตํ ๋ณ๋ช
์์ ๋ ๋ฒ์งธ ํธ์ถ์์ b
๋ฅผ ์ฌ์ฉํฉ๋๋ค(๋ชจ๋ &mat[0]
๊ฐ๋ฆฌํด).
๋๋๊ฒ๋ GCC๋ ๋ค๋ฅธ ์ถ๋ ฅ์ผ๋ก ์ด๊ฒ์ ์๋ชป ์ปดํ์ผํฉ๋๋ค. (-O0์ clang๊ณผ GCC๋ ๋ชจ๋ 7 10
์ถ๋ ฅํฉ๋๋ค. ; clang at -O3์ 7 7
์ถ๋ ฅํ๊ณ , -O3์ GCC๋ 10 7
์ถ๋ ฅํฉ๋๋ค.) ์ด, ์ ๋ง ๊ทธ๋ฌ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค. ๋ญ๊ฐ๋ฅผ ๋ง์น๊ณ ๊ฒฐ๊ตญ UB๋ฅผ ์ถ๊ฐํ์ง๋ง ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค ...
* ๊ทธ๊ฒ๋ณด๋ค ์กฐ๊ธ ๋ ๋ณต์กํ์ง๋ง ์ด ๊ฒฝ์ฐ copy
๋ ํฌ์ธํฐ ์ฐ์ ์ ์ฌ์ฉํ์ง ์๊ณ ๋ ํฌ์ธํฐ์ ๋ชจ๋ ์ฐ๊ธฐ ๋๋ฌธ์ a != b
๊ฐ ์๋ ํธ์ถ์ ๋ํด ๋ถ๋ฑ์
ํ , ๊ฐ์ ์ค๋ช ์ ์ฐพ๊ธฐ ์ํด
์ ๋ง ์ข์ ํ์ด๋ฐ์ด๋ค์ ^^ ๊ฑฐ์ ๊ฐ์ ์ถ์ ํ ์คํธ ์ผ์ด์ค๋ก ๊ฐ์ ๊ฒฐ๋ก ์ ๋๋ฌํ์ต๋๋ค :)
์ ๋ผ์ธ์ ๋ฐ๋ผ ์๋ง๋ ๋ญ๊ฐ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด https://github.com/llvm-mirror/llvm/blob/54d4881c352796b18bfe7314662a294754e3a752/lib/Transforms/Utils/InlineFunction.cpp#L801์ ๋ํ LoopUnrollPass์ผ๋ก ์ํ ํ ํ์๊ฐ์๋ค.
์ด ๋ฌธ์ ์ ๋ํ LLVM ๋ฒ๊ทธ ๋ณด๊ณ ์๋ฅผ https://bugs.llvm.org/show_bug.cgi?id=39282 ์์ ์ ์ถํ์ต๋๋ค
๊ทธ๋ฆฌ๊ณ โ ์์ ์ฑ์ ์ํด ์ด๊ฒ์ ์ธ๊ธํ ๊ฒ โ ๋ด C ํ ์คํธ ์ผ์ด์ค๋ฅผ ์๋ชป ์ปดํ์ผํ๊ธฐ ๋๋ฌธ์ GCC์ ๋ฒ๊ทธ ๋ณด๊ณ ์๋ฅผ ์ ์ถํ์ต๋๋ค. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87609
๋ถ๋ฅ: ์ด ๋ด์ฉ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฝ๊ณ ์๋ค๋ฉด LLVM ์์ ์ฌํญ์ด ์น์ธ๋ ๊ฒ์ ๋๋ค(https://reviews.llvm.org/D9375). ์ค์ ๋ก LLVM์ผ๋ก ๋ณํฉํ๋ ๊ฒ์ด ๋ฌด์์ ์๋ฏธํ๋์ง, ๋๋ ์ธ์ ๊ทธ๋ฐ ์ผ์ด ๋ฐ์ํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. LLVM์ ๊ฐ์ ํ๋ก์ธ์ค์ ๋ํด ๋ ์ ์๊ณ ์๋ ์ฌ๋์ด ๋ฌธ์ ๊ฐ ํ์ฌ ์์ ๋์๋์ง(๊ทธ๋ฆฌ๊ณ ์ด๋ค ๋ฒ์ ์ ๋ํด) ํ์ธํด์ผ ํฉ๋๋ค.
๋ณํฉ๋์ง ์์๊ณ ๊ฒํ ํ๋ก์ธ์ค๊ฐ ์ฝ๊ฐ ์ด์ํ๊ณ ์น์ธํ ์ฌ๋์ ๋ ์ด์ ํจ์น๋ฅผ ๊ฒํ ํ์ง ์์ต๋๋ค.
"์ ์ฒด ์ ํ" ํจ์น ์ธํธ ๋ก ํ ์คํธํ๋ผ๋ ์์ฒญ ์ด ์์์ต๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ์ด ํจ์น ์ธํธ๊ฐ ์ ์ฉ๋ llvm ์์ Rust์์ noalias๋ฅผ ๋ค์ ํ์ฑํํ๋ ค๊ณ ์๋ํ๋ค๋ฉด ์๋ง๋ ๊ฐ์น๊ฐ ์์ ๊ฒ์ ๋๋ค.
๊ธฐ๊บผ์ด ๊ทธ๋ ๊ฒ ํ๋ ค๊ณ ํฉ๋๋ค.
์ ๋นํ ๊ฐ๋ ฅํ ์๋ฒ(48 HT ์ฝ์ด, 128G ๋จ)์ ์ก์ธ์คํ ์ ์์ผ๋ฉฐ ํจ์น๋ก ๋ชจ๋ ๊ฒ์ ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ถํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์๋ํ๋ ๋๊ตฌ ๋ชจ์์ด ์์ผ๋ฉด ์ด๋ค ์์๋ฅผ ์ฌ์ฉํด ๋ณด๋ผ๊ณ ๊ถํ์๊ฒ ์ต๋๊น?
llvm์ ์
์คํธ๋ฆผ ๋ง์คํฐ ์์ ๋ชจ๋ Rust ๊ด๋ จ ์ปค๋ฐ ์ ๋ณํฉํ ๋ค์ ํจ์น ๋ฅผ ์ ์ฉํ์ต๋๋ค.
๊ฒฐ๊ณผ ๋ถ๊ธฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. https://github.com/PaulGrandperrin/llvm-project/tree/llvm-master-with-rustlang-patches-and-D69542
์ด์ ๋๊ตฌ ๋ชจ์์ ์ปดํ์ผํ๊ณ ์๋ํด ๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ Rust๊ฐ ์ค์ ๋ก noalias๋ฅผ ๋ด๋ณด๋ด๋๋ก https://github.com/rust-lang/rust/pull/54639๋ก ๋๋๋ ค์ผ ํฉ๋๋ค.
๊ฐ์ฅ ๋จผ์ ์๋ํ ์ข์ ๊ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
pub fn adds(a: &mut i32, b: &mut i32) {
*a += *b;
*a += *b;
}
๋ค์๊ณผ ๊ฐ์ด ์ปดํ์ผ๋๋์ง ํ์ธํฉ๋๋ค.
example::adds:
mov eax, dword ptr [rsi]
add eax, eax
add dword ptr [rdi], eax
ret
๊ทธ๋ฆฌ๊ณ ์๋
example::adds:
mov eax, dword ptr [rdi]
add eax, dword ptr [rsi]
mov dword ptr [rdi], eax
add eax, dword ptr [rsi]
mov dword ptr [rdi], eax
ret
๋ค์์ผ๋ก https://github.com/rust-lang/rust/issues/54462#issue -362850708์ ์ฝ๋๊ฐ ๋ ์ด์ ์๋ชป ์ปดํ์ผ๋์ง ์๋์ง ํ์ธํฉ๋๋ค.
# 54639๋ ์์ต๋๋ค @jrmuizel์ฃผ์ ์ '์ต์ํ์ ์ฌ์ ์ฅ์น @nagisa์ ํฌํจํ๋ ์๋ก์ด ์ปดํ์ผ๋ฌ ์ํ๊ณผ # 54462์ ๋ํํฉ๋๋ค. ์ ์ฒด ๋๋๋ฆฌ๊ธฐ๊ฐ ์์๋๋ก ๋์ง ์์ ์ ์์ต๋๊น?
AFAIK๋ ์ผ๋ถ ๊ธฐ๋ณธ ํ๋๊ทธ( -Zmutable-noalias=yes
๋ก ์ฌ์ ์ํ ์ ์์)๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ์ ๊ดํ ๊ฒ์ด๊ณ ์ธ๊ธ๋ ํ
์คํธ ํ์ผ์ ์๋์ผ๋ก ์ปดํ์ผํ ์ ์๊ธฐ ๋๋ฌธ์ ํฌํจ ์ฌ๋ถ๊ฐ ์ค์ํ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์์๋ค์ํผ, ์ ๋ ์ฌ์ ํ LLVM์ ๋น๋ํ๋ ค๊ณ ์๋ํ๊ณ ์์ง๋ง ์ง๊ธ์ Rust ๊ด๋ จ ํจ์น๊ฐ ์ ์ฉ๋๊ฑฐ๋ ์ ์ฉ๋์ง ์์ ์ปดํ์ผ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค(์: ์ ์คํธ๋ฆผ์ llvm ๋ง์คํฐ + ํจ์น๋ ์คํจ).
In file included from /usr/include/c++/8/cmath:45,
from /opt/rust/src/llvm-project/llvm/include/llvm-c/DataTypes.h:28,
from /opt/rust/src/llvm-project/llvm/include/llvm/Support/DataTypes.h:16,
from /opt/rust/src/llvm-project/llvm/include/llvm/ADT/Hashing.h:47,
from /opt/rust/src/llvm-project/llvm/include/llvm/ADT/ArrayRef.h:12,
from /opt/rust/src/llvm-project/llvm/include/llvm/Transforms/Utils/NoAliasUtils.h:16,
from /opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:13:
/opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp: In function โvoid llvm::cloneNoAliasScopes(llvm::ArrayRef<llvm::MetadataAsValue*>, llvm::DenseMap<llvm::MDN
ode*, llvm::MDNode*>&, llvm::DenseMap<llvm::MetadataAsValue*, llvm::MetadataAsValue*>&, llvm::StringRef, llvm::LLVMContext&)โ:
/opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:174:30: error: no matching function for call to โllvm::AliasScopeNode::AliasScopeNode(double)โ
llvm::AliasScopeNode SNAN(MD);
^~~~
In file included from /opt/rust/src/llvm-project/llvm/include/llvm/IR/TrackingMDRef.h:16,
from /opt/rust/src/llvm-project/llvm/include/llvm/IR/DebugLoc.h:17,
from /opt/rust/src/llvm-project/llvm/include/llvm/IR/Instruction.h:21,
from /opt/rust/src/llvm-project/llvm/include/llvm/IR/BasicBlock.h:22,
from /opt/rust/src/llvm-project/llvm/include/llvm/IR/Instructions.h:27,
from /opt/rust/src/llvm-project/llvm/include/llvm/Transforms/Utils/NoAliasUtils.h:22,
from /opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:13:
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1446:12: note: candidate: โllvm::AliasScopeNode::AliasScopeNode(const llvm::MDNode*)โ
explicit AliasScopeNode(const MDNode *N) : Node(N) {}
^~~~~~~~~~~~~~
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1446:12: note: no known conversion for argument 1 from โdoubleโ to โconst llvm::MDNode*โ
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1445:3: note: candidate: โconstexpr llvm::AliasScopeNode::AliasScopeNode()โ
AliasScopeNode() = default;
^~~~~~~~~~~~~~
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1445:3: note: candidate expects 0 arguments, 1 provided
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1441:7: note: candidate: โconstexpr llvm::AliasScopeNode::AliasScopeNode(const llvm::AliasScopeNode&)โ
class AliasScopeNode {
^~~~~~~~~~~~~~
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1441:7: note: no known conversion for argument 1 from โdoubleโ to โconst llvm::AliasScopeNode&โ
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1441:7: note: candidate: โconstexpr llvm::AliasScopeNode::AliasScopeNode(llvm::AliasScopeNode&&)โ
/opt/rust/src/llvm-project/llvm/include/llvm/IR/Metadata.h:1441:7: note: no known conversion for argument 1 from โdoubleโ to โllvm::AliasScopeNode&&โ
/opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:177:31: error: request for member โgetNameโ in โ__builtin_nans(((const char*)""))โ, which is of non-class ty
pe โdoubleโ
auto ScopeName = SNAN.getName();
^~~~~~~
/opt/rust/src/llvm-project/llvm/lib/Transforms/Utils/NoAliasUtils.cpp:187:39: error: request for member โgetDomainโ in โ__builtin_nans(((const char*)""))โ, which is of non-class
type โdoubleโ
const_cast<MDNode *>(SNAN.getDomain()), Name);
^~~~~~~~~
[ 75%] Building CXX object lib/Target/Hexagon/CMakeFiles/LLVMHexagonCodeGen.dir/RDFCopy.cpp.o
make[2]: *** [lib/Transforms/Utils/CMakeFiles/LLVMTransformUtils.dir/build.make:635: lib/Transforms/Utils/CMakeFiles/LLVMTransformUtils.dir/NoAliasUtils.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
LLVM ๋ง์คํฐ๊ฐ ์ด๋ฏธ ํจ์น์ ๋๊ธฐํ๋์ง ์์๊ณ (ํจ์น์ ํฌ๊ธฐ์ LLVM ๋ง์คํฐ๊ฐ ์ด๋ํ๋ ์๋๋ฅผ ๊ณ ๋ คํ ๋ ๋ฐ์ํ ์ ์์) LLVM ๋ง์คํฐ์ ์ด์ ๋ฒ์ ์ ๋ํด ๋น๋ํด์ผ ํฉ๋๊น? ์ด์ ๋ํด ํจ์น ์์ฑ์์๊ฒ ํ์ ๋ณด๋ด๋ ๊ฒ์ด ์ข์ต๋๋ค.
๊ทธ๊ฒ์ด ๋ฐ๋ก ๋ด๊ฐ ํ๊ณ ์๋ ์ผ์ด๋ฉฐ, ํจ์น๋ก ๋น๋๋๋ ์ด์ ๋ฒ์ ์ ์ฐพ์ผ๋ ค๊ณ ๋ ธ๋ ฅํ๊ณ ์์ต๋๋ค :-)
๋๋ ์ด์ ๋ฌธ์ ๊ฐ llvm/master๊ฐ ์๋๋ผ ํจ์น์ ์๋ค๊ณ ํ์ ํฉ๋๋ค.
์ฌ์ ํ ํจ์น์ ํธํ๋๋ llvm/master์ ๊ฐ์ฅ ์ค๋๋ ์ปค๋ฐ์ https://github.com/llvm/llvm-project/commit/5b99c189b3bfc0faa157f7ca39652c0bb8c315a7 ์ด์ง๋ง ๊ทธ ๋ฉ๋ฆฌ๊น์ง ํจ์น๊ฐ ์ปดํ์ผ๋์ง ์์ต๋๋ค.
๋๋ ์ง๊ธ C++๋ฅผ ์ดํดํ๋ ค๊ณ ํ๊ธฐ์๋ ๋๋ฌด ํผ๊ณคํ๊ณ ๊ฒ์ผ๋ฅด๋ค. ๋๋ ๋ด์ผ ๋ค์ ์๋ํ ๊ฒ์ด๋ค.
๊ทธ ๋์ ๋๊ตฐ๊ฐ๊ฐ ํจ์น ์์ฑ์์๊ฒ ์ฐ๋ฝํ์ฌ ๋์์ ์์ฒญํ ์ ์์ต๋๊น?
Rustllvm ์ ํจ์นํ์ง ์๊ณ (์ค์ ๋ก ๋น๋ํ ํ) Rust์ ํจ๊ป ๋ง์คํฐ LLVM์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. AFAIK๋ ํ์ฌ ๋ฆด๋ฆฌ์ค 6-9๋ง ์ง์ํฉ๋๋ค.
@mati865 ๋จผ์ ๋ฌ์คํธ์ llvm-9 ํฌํฌ์ ํจ์น๋ฅผ ์ ์ฉํด ๋ณด์์ง๋ง ์ญ์ ๋ง๋ง์น ์์์ต๋๋ค...
ํจ์น๋ ๋ถ๋ช ํ llvm/ llvm-project@82d3ba87d06f9e2abc6e27d8799587d433c56630์ ์๋จ์ ๊ธฐ๋ฐ์
@jrmuize ๊ฐ์ฌํฉ๋๋ค ์๋ํด๋ณด๊ฒ ์ต๋๋ค!
๊ทธ ๋์ llvm master๋ก ๋น๋ํ๋๋ก rustllvm ์ ์ฑ๊ณต์ ์ผ๋ก ์ ์ฉํ ์ ์์์ต๋๋ค.
@PaulGrandperrin ์ ํ, ์ ๋ฐ์ดํธ๊ฐ ์์ต๋๊น?
ํ์ค์ ์ผ๋ก ๋งํด์, ํฌ๊ธฐ๋ฅผ ๊ณ ๋ คํ ๋ ์ด ํจ์น๊ฐ ๋ณํฉ๋ ์์ ์ผ์ ๊ณผ ์ ์ฒด ๊ฐ๋ฅ์ฑ์ ์ผ๋ง์ ๋๊น?
@MSxDOS LLVM ๊ฐ๋ฐ์์๊ฒ ๋ฌป๊ณ ์ถ์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ํจ์น์ ํฌ๊ธฐ๊ฐ ํจ์น๊ฐ ๋ณํฉ๋๊ธฐ๋ฅผ ์ํ๋ ์์ ์์ ์๊ตฌ๋ณด๋ค ๋ ์ค์ํ ๊ฒ์ผ๋ก ์์ํ๋ฏ๋ก LLVM์ด ํจ์น๋ฅผ ๋ณด๊ณ ์ถ์ดํ๋ ์ ๋๊ฐ ๋ฌธ์ ์ ๋๋ค.
๋ด๊ฐ ๋ณธ ์ต์ ์ํ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. https://reviews.llvm.org/D69542#1836439
https://github.com/bytecodealliance/cranelift~~ https://github.com/bjorn3/rustc_codegen_cranelift๊ฐ ์๋ ํ๋ฉด ์ด๋ ์์ ์์ ๊ด๋ จ์ฑ์ด ํฉ๋๋ค.
@leeoniya , opt ๋น๋์ ํฌ๋ ์ธ ๋ฆฌํํธ๋ฅผ ์ฌ์ฉํ ๋จ๊ธฐ ๊ณํ์ ์์ต๋๋ค. ํฌ๋ ์ธ ๋ฆฌํํธ์๋ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ ๋ฐ ํ์ํ ์ต์ ํ ์์ ์ด ๋ง์ด ์์ต๋๋ค.
์ด ์ต์ ์์ด ์จ๋ฆฌ์ด์ฑ์ด ์์ ์ ์๋ค๊ณ ๊ฐ์ ํ๋ ๊ฒ๊ณผ ๊ด๋ จํ์ฌ ์ปดํ์ผ๋ฌ๊ฐ ์ผ๋ง๋ ๋ณด์์ ์ธ์ง ์๊ณ ๋๋์ต๋๋ค. ์๋ฅผ ๋ค์ด:
fn baz(s: &mut S) {
if s.y < 10 {
s.x = foo();
}
if s.y < 5 {
s.x = foo();
}
}
&mut
ํตํด ๊ตฌ์กฐ์ฒด ๋ฉค๋ฒ์ ์ก์ธ์คํ๊ธฐ ๋๋ฌธ์ s.x
๋ฐ s.y
๊ฐ ๋ณ์นญ์ ์ง์ ํ ์ ์๋ค๊ณ ๊ฐ์ ํ๋ฏ๋ก s.y
๋ํด ํ๋๊ฐ ์๋ ๋ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๊ฐ ํ์ํฉ๋๋ค. &mut
๋ฅผ ํตํ ํ์ ์ฝ๊ธฐ/์ฐ๊ธฐ ํ์๋ฅผ ์ผ๋ฐ์ ์ธ ํ๋ก๊ทธ๋จ์์ ์ธํฐ๋ฆฌ๋ธํด์ผ ํ๋ ํ์๋ฅผ ๊ณ ๋ คํ ๋ ์ ๋ง ๋ถํํ ์ผ์
๋๋ค.
ํธ์ง: ์ผ๋ถ ํ
์คํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฉด ์ด๋ฌํ ๋ชจ๋ ์ฝ๊ธฐ/์ฐ๊ธฐ์ ์ํฅ์ ๋ฏธ์น์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋๋ -Z mutable-noalias
๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ์์์ ์ด์ค ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๊ฐ ์์ ๋๋ฏ๋ก ์ผ๋ถ ๊ฒฝ์ฐ๊ฐ ์ค๋จ๋ ์ ์์ต๋๋ค.
@PaulGrandperrin llvm@9fb46a452d4e5666828c95610ceac8dcd9e4ce16์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์ด ํจ์น์ ์ ๋ฒ์ ์ด https://reviews.llvm.org/D69542์ ์์ต๋๋ค. ๋ค์ ์คํํด ๋ณด์๊ฒ ์ต๋๊น?
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๊ฐ๋จํ C ํ ์คํธ ์ผ์ด์ค๋ก ์ถ์ํ์ต๋๋ค(-O3 ๋ฐ -O0์์ ์ปดํ์ผํ๊ณ ์ถ๋ ฅ ๋น๊ต).
์ฐธ๊ณ ์ ๊ฑฐํ๋ฉด ๊ฒ์
restrict
์ ๋๋ฑํ Cnoalias
, ๋์์ ์ฌ๋ฐ๋ฅธ ๊ฒ์ ๋๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณassert(a != b)
๊ฐ ํต๊ณผํ์ฌrestrict
๋ก ํธ์ถํ์ฌ UB๊ฐ ๋ฐ์ํ ์ ์์์ ์ฆ๋ช ํฉ๋๋ค.๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง :
mat[0]
๊ฐmat[idxs[1]]
๋๋mat[1]
์ ๋ณ์นญ์ ์ง์ ํ ์ ์๋ค๊ณ ์๊ฐํ๋ฏ๋กmat[0] = 7;
์mat[idxs[2]] = mat[0];
์ฌ์ด์์ ๋ณ๊ฒฝํ ์ ์์ผ๋ฏ๋ก ์์ ํฉ๋๋ค. ํ์๋ฅผmat[idxs[2]] = 7;
๋ก ์ต์ ํํ๊ธฐ ์ํ ์ ์ญ ๊ฐ ๋ฒํธ ๋งค๊ธฐ๊ธฐ .ํ์ง๋ง
mat[0]
๋mat[idxs[1]]
๋ณ์นญ์ ์ฌ์ฉํฉ๋๋ค. ์๋ํ๋ฉดidxs[1] == 0
์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ&mat[idxs[1]]
๊ฐcopy
์ ๋ฌ๋๋ ๋ ๋ฒ์งธ ๋ฐ๋ณต์์ ๋ค๋ฅธ ์ธ์๊ฐ&mat[1]
์ด๊ธฐ ๋๋ฌธ์ ๊ทธ๋ ๊ฒ ํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ์ฝ์ํ์ง ์์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด ์ LLVM์ ๊ทธ๋ ๊ฒ ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๊น?๊ธ์, ๊ทธ๊ฒ์
copy
๊ฐ ์ธ๋ผ์ธ๋๋ ๋ฐฉ์๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค.noalias
ํจ์ ์์ฑ์ ๋ค์๊ณผ ๊ฐ์ด ๋ก๋ ๋ฐ ์ ์ฅ ์ง์นจ์์!alias.scope
๋ฐ!noalias
๋ฉํ๋ฐ์ดํฐ๋ก ๋ฐ๋๋๋ค.์ผ๋ฐ์ ์ผ๋ก ํจ์๊ฐ ์ฌ๋ฌ ๋ฒ ์ธ๋ผ์ธ๋๋ ๊ฒฝ์ฐ ๊ฐ ๋ณต์ฌ๋ณธ์ alias.scope ๋ฐ noalias์ ๋ํด ๊ณ ์ ํ ID๋ฅผ ๊ฐ์ ธ์ค๋ฉฐ, ์ด๋ ๊ฐ ํธ์ถ์ด
noalias
(restrict
at C level), ์ด๋ ๊ฐ ํธ์ถ์ ๋ํด ๋ค๋ฅธ ๊ฐ์ ๊ฐ์ง ์ ์์ต๋๋ค.๊ทธ๋ฌ๋ ์ด ๊ฒฝ์ฐ ๋จผ์ ํจ์๊ฐ ๋ฃจํ์ ์ธ๋ผ์ธ๋ ๋ค์ ๋ฃจํ๊ฐ ํด์ ๋ ๋ ์ธ๋ผ์ธ๋ ์ฝ๋๊ฐ ๋ณต์ ๋๋ฉฐ ์ด ์ค๋ณต์ผ๋ก ID๊ฐ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. ์ด๊ฒ ๋๋ฌธ์, LLVM์ ์ ํ ์๊ฐํ์ง
a
'์ ์ด๋ค๊ณผ์ ์บ ๋ณ์นญ์b
, ๊ฑฐ์ง์,'๋๋ฌธ์a
์ฒซ ๋ฒ์งธ์ ์ธ ๋ฒ์งธ ํตํ ๋ณ๋ช ์์ ๋ ๋ฒ์งธ ํธ์ถ์์b
๋ฅผ ์ฌ์ฉํฉ๋๋ค(๋ชจ๋&mat[0]
๊ฐ๋ฆฌํด).๋๋๊ฒ๋ GCC๋ ๋ค๋ฅธ ์ถ๋ ฅ์ผ๋ก ์ด๊ฒ์ ์๋ชป ์ปดํ์ผํฉ๋๋ค. (-O0์ clang๊ณผ GCC๋ ๋ชจ๋
7 10
์ถ๋ ฅํฉ๋๋ค. ; clang at -O3์7 7
์ถ๋ ฅํ๊ณ , -O3์ GCC๋10 7
์ถ๋ ฅํฉ๋๋ค.) ์ด, ์ ๋ง ๊ทธ๋ฌ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค. ๋ญ๊ฐ๋ฅผ ๋ง์น๊ณ ๊ฒฐ๊ตญ UB๋ฅผ ์ถ๊ฐํ์ง๋ง ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค ...* ๊ทธ๊ฒ๋ณด๋ค ์กฐ๊ธ ๋ ๋ณต์กํ์ง๋ง ์ด ๊ฒฝ์ฐ
copy
๋ ํฌ์ธํฐ ์ฐ์ ์ ์ฌ์ฉํ์ง ์๊ณ ๋ ํฌ์ธํฐ์ ๋ชจ๋ ์ฐ๊ธฐ ๋๋ฌธ์a != b
๊ฐ ์๋ ํธ์ถ์ ๋ํด ๋ถ๋ฑ์