[過去ログ] Qiita 3 - キータぞ、来たぞ、キータだぞー (1002レス)
前次1-
抽出解除 必死チェッカー(本家) (べ) 自ID レス栞 あぼーん

このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
357
(1): デフォルトの名無しさん [sage] 2023/08/24(木) 08:31:12.59 ID:jcLl4hPI(1/3) AAS
こちらでも Rust(rustc)=C(gcc)>>>C(clang) となった
gccとrustcが同じ最適化をしてると思われる
確認のためLLVM IRを吐くrustcとclangでどのようにコードが異なるか調べてみた

まずclangによるLLVM IR生成
$ clang -S -emit-llvm -O2 -o fibonacci_cl.ll fibonacci.c
そのうちfibonacci()関数部分を抜粋すると以下のコードとなった

; Function Attrs: nounwind readnone uwtable
define dso_local i32 @fibonacci(i32 %0) local_unnamed_addr #0 {
 %2 = icmp ult i32 %0, 2
 br i1 %2, label %9, label %3

3: ; preds = %1
 %4 = add nsw i32 %0, -2
 %5 = tail call i32 @fibonacci(i32 %4)
 %6 = add nsw i32 %0, -1
 %7 = tail call i32 @fibonacci(i32 %6)
 %8 = add nsw i32 %7, %5
 ret i32 %8

9: ; preds = %1
 ret i32 %0
}

元のCコードそのままでnが2未満すなわち0と1の時はそのまま返して
それ以外は fibonacci(n-2) + fibonacci(n-1) を返している
最適化をしていないのでclangがgccよりも遅いのはこれで納得
358
(2): デフォルトの名無しさん [sage] 2023/08/24(木) 08:33:36.30 ID:jcLl4hPI(2/3) AAS
次にrustcによるLLVM IR生成
$ rustc -C opt-level=2 --emit llvm-ir -o fibonacci_rs.ll fibonacci.rs
そのうちfibonacci()関数部分を抜粋すると以下のコードとなった

; fibonacci::fibonacci
; Function Attrs: nofree nosync nounwind nonlazybind memory(none) uwtable
define internal fastcc noundef i32 @_ZN9fibonacci9fibonacci17h1af4b62ef57b502cE(i32 noundef %n) unnamed_addr #4 {
start:
 %switch1 = icmp ult i32 %n, 2
 br i1 %switch1, label %bb8, label %bb5

bb5: ; preds = %start, %bb5
 %n.tr3 = phi i32 [ %_7, %bb5 ], [ %n, %start ]
 %accumulator.tr2 = phi i32 [ %0, %bb5 ], [ 0, %start ]
 %_5 = add i32 %n.tr3, -2
; call fibonacci::fibonacci
 %_4 = tail call fastcc noundef i32 @_ZN9fibonacci9fibonacci17h1af4b62ef57b502cE(i32 noundef %_5)
 %_7 = add i32 %n.tr3, -1
 %0 = add i32 %_4, %accumulator.tr2
 %switch = icmp ult i32 %_7, 2
 br i1 %switch, label %bb8, label %bb5

bb8: ; preds = %bb5, %start
 %accumulator.tr.lcssa = phi i32 [ 0, %start ], [ %0, %bb5 ]
 %n.tr.lcssa = phi i32 [ %n, %start ], [ 1, %bb5 ]
 %accumulator.ret.tr = add i32 %n.tr.lcssa, %accumulator.tr.lcssa
 ret i32 %accumulator.ret.tr
}

clangの場合>>357とは異なり「call」によるfibonacci()呼び出しが一つとなり最適化されている
359
(1): デフォルトの名無しさん [sage] 2023/08/24(木) 08:41:31.44 ID:jcLl4hPI(3/3) AAS
ちなみに>>358のRustコンパイラが吐いたLLVM IRのコードを
見やすくC言語に翻訳するとこういうコードになっている
(このコードはLLVM自体による最適化をする前であることに注意)

int fibonacci(int n) {
 if (n < 2) {
  return n;
 }
 int f = 0;
 while (1) {
  f += fibonacci(n - 2);
  n = n - 1;
  if (n < 2) {
   return f + 1;
  }
 }
}

これはgccが吐いたアセンブラコードと同じ構造であり
rustcとgccは同様の最適化をしていることがわかる

したがって実測結果の Rust(rustc)=C(gcc)>>>C(clang) が生成コードによっても裏付けられた
結論「同様の最適化をしているRustとC(gcc)の両者が最も速い」
前次1-
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 0.040s