コンパイラ

上のコードで、sqをインライン展開したあとに続けて効く最適化と、その結果として正しいものはどれか。

static int sq(int v) { return v * v; }
int g(void) { return sq(6) + 1; }
  1. A共通部分式の削除により、g は sq を2回呼ぶようになる
  2. B定数畳み込みにより、g は 37 を返すだけのコードになる
  3. Cループ展開により、v * v が6回の足し算に置き換わる
答えと解説を見る

正解:B. 定数畳み込みにより、g は 37 を返すだけのコードになる

sqをインライン展開すると、g の中は return 6 * 6 + 1; となり、掛け算の材料がすべて定数になります。続けて定数畳み込みを行うと 6 * 6 = 36、36 + 1 = 37 と計算でき、gは37を返すだけのコードになります。インライン展開は、呼び出しの手間をなくすだけでなく、このように呼び出し元の値を使った最適化を可能にするのが大きな利点です。ここにはループがなく、sqを2回呼ぶようになることもありません。

  • A. 呼び出しはむしろなくなります。
  • B. 正しい。展開後に定数畳み込みが効き、37だけが残ります。
  • C. このコードにループはありません。
この分野を解く 分野ページへ

コンパイラのほかの問題

  1. ソフトウェアパイプライン化(ソフトウェアパイプライニング)の説明として正しいものはどれか。
  2. コンパイラが、浮動小数点数の足し算 (a + b) + c を、厳密な設定のもとでは a + (b + c) に勝手に並べ替えない理由として正しいものはどれか。
  3. コンパイラの自動ベクトル化で使われる命令の種類として正しいものはどれか。
  4. コンパイラの最適化が守らなければならない基本的な条件として正しいものはどれか。
  5. コード生成の段階の一つである命令選択(インストラクションセレクション)の説明として正しいものはどれか。