最近 gcc の最適化オプションに関連するトラブルで悩んでいる・・・
gcc 4.8 から導入されたと言われる「LTO」(Link-Time Optimization)は、ソース単位
を超えた最適化を行う。
非常に有用で、サイズ、スピード、共に改善するようだ。
RL78では、SDカードを扱うようになってバイナリーサイズが肥大化してきたので、
積極的に「-flto」を追加するようになった。
バイナリーが10%程小さくなり、大きな効果がある事が分かった。
しかし・・・
最近、RL78のフラッシュ書き込みプログラムの実装を進めて、MSYS2環境では
書き込みが出来るようになった。
そこで、OS-XやLinuxでもテストを始めてみたのだが、書き込みプログラムは
MSYS2以外では動作しなかった。
まあこれは、仕方無い、原因を特定して修正するだけなのだが、問題は、OS-X、
Linuxでビルドした rl78-elf-gcc だった。
明らかにMSYS2で作成したバイナリーと異なっている。
調べると、どうやら、どこからも参照されないテーブルや関数が、全て無くなっていて、
最終的なバイナリーに含まれていない。
これは、主に、割り込みベクターや、割り込みプログラムなどで、無ければ当然動作し
ない。
しかしながら、MSYS2でビルドしたバイナリーには、ちゃんと含まれている。
つまり、MSYS2で作成した gcc と、OS-X、Linuxでビルドした gcc では
異なっているという事だ、確かに、ファイルパスの扱いなどが違うので、異なってはい
ると思うが、ビルドしたバイナリーが異なるのは、非常に問題だ。
リンカースクリプト内には、「KEEP」宣言もしてあっても、削除されてしまう。
※これは、MSYS2 でビルドした gcc では起こらない。
とりあえず、「#pragma GCC optimize ("O0")」をベクター領域で宣言する事で、回避
できる事は分かったものの、釈然としない・・
まだ LTO は実装が始まったばかりで、「枯れていない」という事なのかもしれない。
それと、RL78では、0x0000~0x2FFFまでの領域は、ミラー領域として、
データ領域のアクセスでは、実際には、0xF0000~0xF2FFFの、データ・
フラッシュ領域がアクセスされるのだが、LTOを使うと、コードが、0x0000~
0x2FFFまでには配置されずに、その領域を有効に使えない為、割り込み駆動のタ
スクをその領域に配置するようにセクションを調整しているものの、これも、全く配置
されない・・・
MSYS2 の gcc では、ちゃんと配置される。
さらに問題は色々あって、RX マイコン用 gcc でも、LTO を使うと、リンカー時に、
gcc がクラッシュする場合があるようだ・・・
これは、プログラムによって、する場合としない場合があるようで、非常に困る。
当面 LTO を使う事ができない。
gcc-5.4.0 で、このバグが直っているかもと思い、試してみたが、駄目のようだ・・・
今更の情報かもしれませんが、GCC for Renesas 4.9.2.201604-GNURL78では、直されているようです。
ご参考までに。
https://gcc-renesas.com/ja/updated-toolchains-available-for-renesas-rx-rl78-targets/#more-1231
(Bug Fix) LTO algorithm removes HardwareVectors in some cases, even though KEEP is used in the linker script. This issue has been fixed.
情報ありがとう御座います。
gcc-4.9.4 で試したのですが、ソースによって、コンパイラーが
クラッシュする場合があるようで、現状では、やはり「使えない」
ようです・・
※これは、M32C、RXマイコンのgccでも同様なようです。
また、KPIT のツールチェインは、オリジナルの gcc を魔改造
して使っており、その修正分で、オリジナル gcc に有効な修正
が反映しているかは不明です。(多分、まだ反映されていない
と思われる)
※KPITのツールチェインを使わない理由として:
・「魔改造」をする必要性は無いと思える事。
※オリジナルgccのオプション指定などで同様な事ができる。
※重要な部分を隠蔽して、内部処理される為、KPITのgcc
でしか動作しないソースコードになってしまう。
・最新のgccに対応するのに時間がかかる。
gccにおける、LTO関係のコードは、5系や6系で、また、別の
方向性に進化しており、まだ十分枯れているとは言えない感じ
です・・