概要
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.