gcc/memo
gcc/memo
まあ適当に…
最適化レベルを -O3 以上にした場合、ループ展開が抑止できない
http://pc11.2ch.net/test/read.cgi/tech/1145357824/963-993 あたり。
963 :デフォルトの名無しさん:2007/10/09(火) 11:05:30 gccのループ展開の抑制について質問させてください。 コードサイズの評価をしようとして、常用している -O3 に ループ展開の抑制だけを加えて -O3 -fno-unroll-loops -fno-peel-loops と したんですが、ループ展開を止めてくれません。どうやればいいんでしょう? gccのバージョンは4.1.2(tarballから展開・パッチなし)、 実行環境はi686-pc-linux-gnuとpowerpc-linuxです(どちらでも現象は同じ)。 問題のコードを直接晒せないので、再現コードを書きます: #define N 5 int foo(int a[]) { int t = 0, i; for (i = 0; i < N; i++) t += a[i]; return t; } 上のように定数回の小ループがあって、ループ回数が少ないと展開するようです。 展開した場合は、ループ構造は削除され、中身が回数分反復されます。 -O2 とすればループ展開を行わなくなります。 でも、ループ展開以外の最適化は -O3 のままにしておきたいんです。 968 :デフォルトの名無しさん:2007/10/09(火) 21:51:46 >>963 4.1.2で色々やってみたけど抑制できなかった 969 :デフォルトの名無しさん:2007/10/09(火) 22:02:20 そこだけソース別けて-O2でコンパイルするとか... 970 :デフォルトの名無しさん:2007/10/09(火) 23:04:35 >>967 了解。今から長いコンパイルを開始します。 971 :963:2007/10/10(水) 00:53:43 >>968 どもです。お手数おかけしてます。やっぱり地味に難しいんでしょうか。 >>969 避けてしまうのはどうにでもできるんですが、ほしいのは 「このコードをこういう条件でコンパイルするとこういう結果になります」という コード評価でして。コードの一部だけ最適化条件を変えるのは できるだけしたくない、という事情です。 ただ、ここで詰まっていてもしょうがないので、 適当なところで見切りをつけますけどね。全体を-O2にしてしまうとか。 4.1.2のmanを調べたら「-O3は-O2に-finline-functions -funswitch-loops -fgcse-after-reloadを足したもの」と書いてあったのですが、 -O2にこれらを足しても-O3と等しくはなりませんでした。うーむ。 972 :デフォルトの名無しさん:2007/10/10(水) 02:02:49 -O3 -fno-unroll-loops でいいんでないの? 973 :デフォルトの名無しさん:2007/10/10(水) 04:53:20 >>971 manは結構いいかげんなのでソースを当たるべし。 974 :デフォルトの名無しさん:2007/10/10(水) 08:52:16 さんざん既出だが、 自分で細かくコントロールしたければ、 -O3, -O2などを使ってはいけない。 981 :デフォルトの名無しさん:2007/10/10(水) 15:35:05 GNU製品のmanなんて宛てにしないでソースで正確なの調べろよ。 982 :デフォルトの名無しさん:2007/10/10(水) 18:33:46 GNU製品のmanなんて信用せずに素直にinfo見ろよな 985 :デフォルトの名無しさん:2007/10/10(水) 20:57:03 infoもこう書いてあるけど `-O3' Optimize yet more. `-O3' turns on all optimizations specified by `-O2' and also turns on the `-finline-functions', `-funswitch-loops' and `-fgcse-after-reload' options. 988 :デフォルトの名無しさん:2007/10/11(木) 08:03:19 >>975 -O2使ったとたんに他の指定は上書きされるのが現実です。 個別に設定しても必ずその通りになるものではないし。 最適化技法間の制約があるので。 暗黙に無効、有効にする時に、Warningも出しません。 ソース読むしかないんです。 989 :デフォルトの名無しさん:2007/10/11(木) 09:27:31 どの最適化をするかくらいならすぐ読めるよね 990 :963:2007/10/12(金) 00:58:21 ソースを読みました。opts.c の decode_options() に最適化オプション読み込みの 基本部分がありました。大雑把には次のような構造でした。 for (i = 1; i < argc; i++) { /* すべての-Oxオプションを通し読み */ } if (optimize >= 1) { flag_hoge = 1; ... } /* -O1以上でのフラグ設定を適用 */ if (optimize >= 2) { flag_geho = 1; ... } /* -O2以上でのフラグ設定を適用 */ ... handle_options(argc, argv, ...); /* 各オプションを処理 */ optimize >= 3 では、flag_inline_functions と flag_unswitch_loops と flag_gcse_after_reload を 1 にしていました。 その箇所だけ読むとmanやinfoの記述は正しいことになるんですが、はて。 結局追いきれませんでした。 それから、>>988の通り、フラグ変数を書き換えてもその情報をどこにも伝えません。 ちょっと不便なような。。。 で、別解なんですが、「-O3 --param max-completely-peeled-insns=0」 と指定してpeelingを止めてしまえば目的を果たせることがわかりました。 この指定で行こうと思います。 991 :デフォルトの名無しさん:2007/10/12(金) 01:22:28 いや、該当するフラグ変数を全ソースで検索しないと。 コンパイル中にフラグの値変ることもあるし。 992 :デフォルトの名無しさん:2007/10/12(金) 02:23:32 >>991 ヒントありがとうございます。flag_unroll_loops と flag_peel_loops に 当たりをつけて探してみました。これだろうな、ってのが出てきました。 tree-ssa-loop.c: static void tree_complete_unroll (void) { if (!current_loops) return; tree_unroll_loops_completely (current_loops, flag_unroll_loops || flag_peel_loops || optimize >= 3); } "optimize" でも軽く眺めてみましたが、フラグではなく最適化レベルの数値を 最適化の適用条件にしている箇所はそれなりに珍しいようです。 993 :デフォルトの名無しさん:2007/10/12(金) 08:47:02 > optimize >= 3 ワラ イヤだねー 994 :デフォルトの名無しさん:2007/10/12(金) 09:03:27 将来を見据えた設計なのでは? 995 :デフォルトの名無しさん:2007/10/12(金) 12:37:26 >>994 断言できる。何も考えてないだけ。