LoginSignup
1
0

More than 5 years have passed since last update.

LLVM:IR:条件分岐コードの作り方

Last updated at Posted at 2019-03-18

概要

LLVMのIRで分岐を実現するためにはIRBuilderクラスのメソッドCreateCondBr()を使います。
分岐先を判定するための評価値へのポインタ、評価値がTrue/Falseであったときのそれぞれのジャンプ先のBasicBlockへのポインタを指定する必要があります。

簡単な例

以下の複数のBasicBlockからなる関数main()の先頭のBasicBlockのお尻をCreateCondBr()を使用して作成したbr命令に入れ替えてみます。(入れ替えることに意味はありません!説明のための例です!)

  • 操作対象のLLVM IR
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  store i32 0, i32* %2, align 4
  br label %3 ; <--ここを入れ替えてみる!

; <label>:3:                                      ; preds = %9, %0
  %4 = load i32, i32* %2, align 4
  %5 = icmp slt i32 %4, 5
  br i1 %5, label %6, label %12

; <label>:6:                                      ; preds = %3
  %7 = load volatile i32, i32* @giData, align 4
  %8 = add nsw i32 %7, 1
  store volatile i32 %8, i32* @giData, align 4
  br label %9

; <label>:9:                                      ; preds = %6
  %10 = load i32, i32* %2, align 4
  %11 = add nsw i32 %10, 1
  store i32 %11, i32* %2, align 4
  br label %3

; <label>:12:                                     ; preds = %3
  %13 = load i32, i32* %1, align 4
  ret i32 %13

  • 入れ替えるためのcppコード
// Fはmain()を指しています!
// 挿入対象をmain関数先頭のBasicBlockに指定
IRBuilder<> Builder(&F.getEntryBlock());
// True時のジャンプ先を2番目のBasicBlockに指定    
BasicBlock * tr = F.getBasicBlockList().getNextNode(F.getBasicBlockList().front());
// False時のジャンプ先を3番目のBasicBlockに指定
BasicBlock * fl = F.getBasicBlockList().getNextNode(*tr);
// 評価値を生成(ここでは簡単のためtrueを生成)
Value * cond = ConstantInt::get(IntegerType::get(context, 1), 1);
// 先頭のBasicBlockのお尻の命令を削除
F.getEntryBlock().getInstList().pop_back();
// ここが本題!!
// condがtrueのとき2番目のBasicBlock
// falseのときは3番目のBasicBlockにジャンプするbr命令を生成している。
// 生成した命令はmain関数先頭のBasicBlock内の命令リストのお尻に追加される。
Builder.CreateCondBr(cond, tr, fl);
  • 入れ替え後のIR
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  store i32 0, i32* %2, align 4
  br i1 true, label %3, label %6 ; <-- 地味ですが入れ替わっています!!

; <label>:3:                                      ; preds = %9, %0
  %4 = load i32, i32* %2, align 4
  %5 = icmp slt i32 %4, 5
  br i1 %5, label %6, label %12

; <label>:6:                                      ; preds = %3, %0
  %7 = load volatile i32, i32* @giData, align 4
  %8 = add nsw i32 %7, 1
  store volatile i32 %8, i32* @giData, align 4
  br label %9

; <label>:9:                                      ; preds = %6
  %10 = load i32, i32* %2, align 4
  %11 = add nsw i32 %10, 1
  store i32 %11, i32* %2, align 4
  br label %3

; <label>:12:                                     ; preds = %3
  %13 = load i32, i32* %1, align 4
  ret i32 %13

まとめ

CreateCondBr()は、例で示したような既存のIRを書き換えるときに使用するケースは少ないと思いますが、今回は説明をサボるために簡単にするために使いました。

自作フロントエンドの作成に役立てば幸いです。

参考

Happy llvm!
Muraak.

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0