Rust: LLVM์ด ๋” ์ด์ƒ ์ž˜๋ชป ์ปดํŒŒ์ผํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ noalias ์ฃผ์„์„ ๋‹ค์‹œ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2018๋…„ 10์›” 06์ผ  ยท  33์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: rust-lang/rust

์ด ๋ฌธ์ œ๋Š” LLVM์˜ ๋ฒ„๊ทธ๋กœ ์ธํ•ด https://github.com/rust-lang/rust/pull/54639 ์— ๋„์ž…๋œ -Zmutable-alias=no ๊ธฐ๋ณธ๊ฐ’์˜ ์‹คํ–‰ ์ทจ์†Œ๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค. cc @nagisa

( ๋ฐ์ž๋ทฐ? )

A-LLVM A-codegen C-tracking-issue I-slow T-compiler

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๊ฐ„๋‹จํ•œ 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๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์—†์Œ์„ ์ฆ๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ :

  1. copy()๊ฐ€ ์ธ๋ผ์ธ๋˜์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.
for (int i = 0; i < 3; i++) {
    mat[idxs[i]] = mat[i%2]; mat[i%2] = 7;
}
  1. LLVM์€ ๋ฃจํ”„๋ฅผ ํ’‰๋‹ˆ๋‹ค.
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]]) */
  1. LLVM์€ 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 ๊ฐ€ ์•„๋‹Œ ํ˜ธ์ถœ์— ๋Œ€ํ•ด ๋ถ€๋“ฑ์‹

๋ชจ๋“  33 ๋Œ“๊ธ€

๋‚˜๋Š” ์—ฌ์ „ํžˆ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ œ๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํฅ๋ฏธ๋กœ์šด ํ‹ฐ์ผ“์€ 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

LLVM ์ด๋“ฑ๋ถ„ ์ถœ๋ ฅ

์ด ํŒŒ์ผ์˜ ๊ฒฝ์šฐ, ์ตœ์ ํ™” 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๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์—†์Œ์„ ์ฆ๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ :

  1. copy()๊ฐ€ ์ธ๋ผ์ธ๋˜์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.
for (int i = 0; i < 3; i++) {
    mat[idxs[i]] = mat[i%2]; mat[i%2] = 7;
}
  1. LLVM์€ ๋ฃจํ”„๋ฅผ ํ’‰๋‹ˆ๋‹ค.
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]]) */
  1. LLVM์€ 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 ์— ํ•‘, ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

https://reviews.llvm.org/D68484

ํ˜„์‹ค์ ์œผ๋กœ ๋งํ•ด์„œ, ํฌ๊ธฐ๋ฅผ ๊ณ ๋ คํ•  ๋•Œ ์ด ํŒจ์น˜๊ฐ€ ๋ณ‘ํ•ฉ๋  ์˜ˆ์ƒ ์ผ์ •๊ณผ ์ „์ฒด ๊ฐ€๋Šฅ์„ฑ์€ ์–ผ๋งˆ์ž…๋‹ˆ๊นŒ?

@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์— ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹คํ–‰ํ•ด ๋ณด์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰