時相論理を用いた
コンパイラ最適化器の
実行の正しさの検査
東京工業大学
佐原 聡一郎 佐々 政孝
研究背景
コンパイラの最適化
重要な技術で研究が盛ん
複雑でバグが混入しやすい
プログラムの意味を変えてしまう致命的なものかも
バグが発見しずらい
最適化器の正しさを保証できないか?
3つのアプローチ
1.
2.
3.
最適化器そのものにバグがないことを検査
最適化の実行に誤りがなかったことを検査
多くのテストによる信頼性の向上
関連研究
1.
バグがないと保証された最適化器
Laceyらの研究 [2002]
CTL-FVとモデル検査による最適化システム
2.
システム上では最適化器の正しさの証明が簡単
扱える最適化に制限がある
最適化の実行に誤りがなかったことの検査
Neculaの研究 [2000]
最適化実行後の記号実行を用いた検査
高速で最適化に依存せず実用的
検査が正しく行える保証がない
目標
最適化器実行の正しさを保証する手法
現実に存在する最適化器を扱えるように
実用的であるように
実装が困難すぎない、現実的な時間内の検査、など
誤った最適化に気付ければよい
最適化器自身の正しさを保証できなくてもよい
毎回の最適化の実行が正しかったかどうか
最適化器の構成
解析
変形
プログラムの解析
変形すべき箇所を探し出す
データフロー方程式など
プログラムの変形
解析により求めた箇所を変形する
提案手法の概要
解析
変形
検査
正しい
変形が正しかったかどうかを検査
変形箇所の満たすべき性質をCTL-FVで記述
実行パスに沿った論理で直観的
モデル検査のコストが小さい
最適化実行後にモデル検査
変形箇所ごとの検査
提案手法の詳細
x=a+b
end
x は使用されない
簡単な無用命令除去
使われない変数への代入文削除
提案手法の詳細
¬E(true U use(x)) ?
x=a+b
使われない変数への代入文削除
rm, x
OK
簡単な無用命令除去
変形箇所の正しさ
x
end
x は使用されない
は以後使用されることはない
¬EF(use(x))
E (true U use( x))
変形箇所にマーク付け
最適化器を拡張(AOP利用)
モデル検査
マークに関するCTL-FV式の検査
最適化器の拡張
optimize() {
pos = analyze()
foreach (p in pos) {
transform(p)
}
}
拡張ポイント
変形を行うコードの箇所
マーク付けコードの挿入
optimize() {
pos = analyze()
foreach (p in pos) {
transform(p)
marking(p)
}
}
transform(p)
marking(p)
AOPの利用
pointcut
transform(p)
weave
marking(p)
CTL-FVの構文と意味
φ:: prop
| φ
|φφ
| Eψ
| Aψ
| Eψ
| Aψ
ψ:: Xφ
| Gφ
|φUφ
|φWφ
ループ不変式移動
ループ不変式を移動
一時変数への代入文を挿入
元の式の計算を一時変数で置換
正しいための条件
挿入箇所
一時変数 t は他で定義されない
x=a+b
E (true U (node(n) def
¬EF(¬node(n)∧def(t))
∧ (t )))
¬rEF(¬node(n)∧def(t))
E (true U (node(n) def (t )))
置換箇所
前方に挿入箇所が必ず存在する
その間、式の値は変わらない
rA(trans(e)
A(trans(e) W
W mark(ins,t,e))
mark(ins, t, e))
*SSA形式を仮定
ループ不変式移動
t=a+b
ループ不変式を移動
一時変数への代入文を挿入
ins,t,e OK
元の式の計算を一時変数で置換
正しいための条件
挿入箇所
一時変数 t は他で定義されない
x=a+b
x=t
rpl,t,e OK
*SSA形式を仮定
E (true U (node(n) def
¬EF(¬node(n)∧def(t))
∧ (t )))
¬rEF(¬node(n)∧def(t))
E (true U (node(n) def (t )))
置換箇所
前方に挿入箇所が必ず存在する
その間、式の値は変わらない
rA(trans(e)
A(trans(e) W
W mark(ins,t,e))
mark(ins, t, e))
ループ不変式移動のバグ
例外の発生する式の移動
計算のないパスに挿入不可
例外が発生するようになるかも
挿入点が追加で満たすべき性質
全てのパスに元々計算があった
A(trueW
Wmark(rpl,t,e))
m ark(rpl, t , e))
A(true
x=a/b
COINSのバグ
未知のバグ
SPECを用いて検査中に発見
テストで発見されなかった潜在的バグ
*SSA形式を仮定
ループ不変式移動のバグ
t=a/b
例外の発生する式の移動
計算のないパスに挿入不可
例外が発生するようになるかも
ins,t,e NG
挿入点が追加で満たすべき性質
全てのパスに元々計算があった
A(trueW
Wmark(rpl,t,e))
m ark(rpl, t , e))
A(true
x=a/b
x=t
rpl,t,e
COINSのバグ
未知のバグ
SPECを用いて検査中に発見
テストで発見されなかった潜在的バグ
*SSA形式を仮定
条件分岐を考慮した定数伝播
B1
t0=0
抽象実行に基づく最適化
プログラムを順にたどることで解析
B2
t1=φ(t0,t3)
t1==0 ?
t2=t1+1
B3
B4
複雑な最適化
Laceyらの手法では行えない最適化
B5
t3=φ(t1,t2)
g=2*t3
g<=0 ?
常にt1==0が成立
B4は通らない
全ての辺を通るかもという前提
⇒ t1が0となることが解析できない
単純なデータフロー方程式でも行えない
本手法による最適化後検査は可能
t1==0が本当に正しいかは検査は可能
B6
*SSA形式
*詳細は省略
条件分岐を考慮した定数伝播
B1
t0=0
抽象実行に基づく最適化
プログラムを順にたどることで解析
B2
t1=φ(t0,t3)
t1==0 ?
t2=t1+1
B3
B4
複雑な最適化
Laceyらの手法では行えない最適化
B5
t3=φ(t1,t2)
g=2*t3 0
g<=0 ?
常にt1==0が成立
B4は通らない
全ての辺を通るかもという前提
⇒ t1が0となることが解析できない
単純なデータフロー方程式でも行えない
本手法による最適化後検査は可能
t1==0が本当に正しいかは検査は可能
B6
*SSA形式
*詳細は省略
COINSの最適化器への適用
行数
拡張
357
2
cstp
1143
5
2
条件分岐付定数伝播
cpyp
143
3
2
(cstp)
コピー伝播(cpyp)
共通部分式除去(cse)
無用命令除去(dce)
cse
408
7
1
dce
480
3
lcm
1259
2
SSA形式
ループ不変式移動(hli)
hli
部分冗長除去(lcm)
拡張箇所は少ない
通常形式
改変
⇒ マークも少ない
探し出すのも容易
ソースの改変もほぼない
ポイントカットの都合のみ
本手法の考察
論理式の記述について
記述量は少ない
変形箇所自体が少ない
論理式は変形箇所一つにつき、1~3行程度
最適化のきちんとした理解が必要
論理式の記述は決して容易というわけではない
最適化器製作者なら可能な範囲か
バグの原因特定の容易さについて
論理式のモデル検査で反例
⇒ 式に関する変形は誤りであった
バグを発見した際の原因特定は容易
本手法の考察
正しさの保証について
検査付コンパイルは高信頼
「誤った最適化に気づかずプログラム実行」とはならない
テストだけでは得られない信頼性
次に最適化コンパイルするプログラムの正しさは保証外
厳密なプログラムの意味保存を示すものではない
論理式を満たす≠プログラムの意味が保存される
ギャップを埋めるための証明が必要になる
ただし、直観的にはほぼ明らかか
Lacey>本手法≒ Necula≫テスト
Laceyらの最適化器は常に正しい(証明付の場合)
ただし、扱えるのは簡単な最適化のみという制限がある
検査時間の計測実験
目的
検査にかかる時間が現実的であることを確かめる
実験環境
Intel Pentium 4 CPU 2.80GHz
Linux 2.6.17-13msmp
JavaVM 1.5.0_08
Heap 256Mbyte、Stack 2Mbyte
COINS 1.4.1
最適化O2 に相当するSSA最適化オプション
GluonJ 1.2
ベンチマーク
SPEC CPU2000 version1.2 から14本
1.m
cf
p
m
m
ke
su
8.a
m
ua
9.a
rt
17
3.e
q
18
18
19
af
ty
7.p
ar
se
r
25
4.g
ap
25
5.v
or
te
x
25
6.b
z ip
2
30
0.t
wo
lf
17
1.s
wi
m
17
2.m
gr
id
17
7.m
es
a
6.c
r
18
18
r
17
5.v
p
p
m
m
su
18
8.a
m
ke
9.a
rt
ua
18
3.e
q
17
p
5.v
or
te
x
25
6.b
z ip
2
30
0.t
wo
lf
17
1.s
wi
m
17
2.m
gr
id
17
7.m
es
a
25
r
rs
e
af
ty
cf
4.g
a
25
7.p
a
19
18
6.c
r
r
5.v
p
18
1.m
17
検査時間の計測実験
最適化時間の比
30
25
5
総コンパイル時間の比
2
1.5
1
0.5
0
コンパイル時間の比較
20
15
10
0
3
2.5
検査on/offの比
最適化時間比
総コンパイル時間比
あくまで参考値
検査した最適化は一部
考察
速度比
最適化のみでは15倍
総コンパイル時間では1.7倍
高速化も十分可能
現実的な時間の範囲内
まとめ
最適化実行後に正しかったかどうかを検査
変形箇所がCTL-FV式を満たせば正しいと判断
最適化後のプログラムをモデル検査
特徴
既存の手書きの最適化器に適用可能
複雑な最適化器でも扱える可能性
バグを発見した際の原因特定が容易
常に検査を行うことで高い信頼性
検査時間は現実的な範囲
今後の課題
正しさの厳密な証明
時相論理による証明はいくつか行われている
Laceyらの証明法、各最適化ごとの証明、など
本手法においても同様にして行えると期待
さらに多くの最適化器に適用
演算の強さ軽減、PREQPなどに適用可能か?
検査の高速化
本手法に特化したモデル検査
データフロー方程式のビットベクトル法の応用
おわり
CTL-FVの例
A(φ1Uφ2)
全パスでφ2の成立までφ1が常に成立
φ2の成立する状態が必ずある
{
s |= A(φ1Uφ2) } = {3,4,8}
A(φ1Wφ2)
全パスで以下のいずれかが成立
{
φ2の成立までφ1が常に成立
φ2が成立せず、永遠にφ1が成立でもよい
ループし続けるパスの考慮の回避
s |= A(φ1Wφ2) } = {3,4,5,6,7,8}
本手法の考察
厳密な意味での正しさについて
厳密な意味での「検証」ではない
式を満たした≠最適化が正しく行われた
厳密には証明が必要
ただし、直観的にはほぼ明らかといえる
Lacey>本手法≒
Necula>テスト
Laceyらの最適化器は常に正しい(証明付の場合)
プログラムは無限にあるので、全テストは無理
次に最適化コンパイルするプログラムの正しさは保証外
条件分岐を考慮した定数伝播
B1
B2
t0=0
抽象実行に基づく最適化
t1=φ(t0,t3)
t1==0 ?
CTL-FVの記述では…
t2=t1+1
B3
常にt1==0
B4は通らない
B4
t1が取る値を解析するのは無理
B5
t3=φ(t1,t2)
g=2*t3
g<=0 ?
t1==0という解析結果の検査は可能
Laceyらの手法では行えない最適化
データフロー方程式でも行えない
本手法では検査可能
Laceyらが扱えない最適化も検査可能
「解析」は「結果の検査」より大変
B6
*詳細は省略
条件分岐を考慮した定数伝播
B1
B2
t0=0
抽象実行に基づく最適化
t1=φ(t0,t3)
t1==0 ?
CTL-FVの記述では…
t2=t1+1
B3
常にt1==0
B4は通らない
B4
t1が取る値を解析するのは不可能
B5
t3=φ(t1,t2)
g=2*t3 0
g<=0 ?
t1==0という解析結果の検査は可能
Laceyらの手法では行えない最適化
データフロー方程式でも行えない
本手法では検査可能
Laceyらが扱えない最適化も検査可能
「解析」は「結果の検査」より大変
B6
*詳細は省略
© Copyright 2026 ExpyDoc