いいえ、少なくとも従来のツールチェーンの仕組みでは不可能です。従来の操作の順序は、すべてのコンパイルが実行されてから、リンクが実行されるというものです。
比較関数をインラインで生成するには、コンパイラは最初にqsort
それ自体のコードをインラインで生成する必要があります(の各インスタンスqsort
は通常、異なる比較関数を使用するため)。ただし、のようなものの場合qsort
、コードの記述について考える前に、通常はコンパイルされて標準ライブラリに配置されます。コードをコンパイルすると、qsort
はオブジェクトファイルとしてのみ使用できます。
そのため、このようなことを行う可能性さえあるためには、コンパイラではなくリンカーにインライン化機能を組み込む必要があります。少なくとも理論的には可能ですが、それは明らかに自明ではありません。少なくとも私の見積もりでは、ソースコードを操作する場合よりもほぼ確実に困難です。また、リンカでコンパイラのような機能をかなり複製する必要があります。また、リンカが機能するのに十分な情報をリンカに提供するために、オブジェクトファイルにかなりの量の追加情報を追加する必要があります。
編集:おそらく、コメントチェーンが言葉遣いだけで本格的な議論にならないように、もっと詳しく説明する必要があります。
伝統的に、リンカーは基本的にかなり単純な種類の獣です。これは、次の4つの主要な要素に分割できるオブジェクトファイルから始まります。
- オブジェクトファイルから生成中の実行可能ファイルにコピーされる(特に指示されている場合を除き、変更されない)ビットのコレクション。
- オブジェクトファイルに含まれるシンボルのリスト。
- によって使用されるシンボルのリストは、オブジェクトファイルによって提供されません。
- アドレスを書き込む必要がある修正プログラムのリスト。
次に、リンカは、あるファイルでエクスポートされ、別のファイルで使用されるシンボルの照合を開始します。次に、ライブラリ(または複数のライブラリ)内のオブジェクトファイルを調べて、さらに多くのシンボルを解決します。ファイルを追加するたびに、必要なシンボルのリストも追加し、それらを満たすことができる他のオブジェクトファイルを再帰的に検索します。
すべてのシンボルを提供するオブジェクトファイルが見つかると、それぞれのビット部分のコレクションを出力ファイルにコピーし、修正レコードが指示する場所に、特定のシンボルに割り当てられた相対アドレスを書き込みます(たとえば、と呼ばれるとprintf
、実行可能ファイルのどこを構成するビットをコピーしたかがprintf
わかり、そのアドレスを呼び出しに入力します)。かなり最近のケースでは、ライブラリからビットをコピーするのではなく、共有オブジェクト/ DLLへの参照を実行可能ファイルに埋め込み、ローダーに任せて、実行時にそのファイルを実際に検索/ロードして、実際のコードを提供することができます。シンボル。
ただし、特に、リンカは従来、コピーするビットのブロックの実際の内容を認識していません。(たとえば)まったく同じリンカーをかなり合理的に使用して、多数の異なるプロセッサーのコードを処理できます。それらがすべて同じオブジェクトと実行可能ファイル形式を使用している限り、問題ありません。
リンク時間の最適化は、それを少なくともある程度変更します。明らかに、コードを最適化するには、従来はリンク時間と見なされていた時間に発生する、ある種の追加のインテリジェンスが必要です。これを行うには(少なくとも)2つの方法があります。
- リンカーにかなりの追加インテリジェンスを組み込む
- インテリジェンスをコンパイラーに保持し、リンカーにそれを呼び出して最適化を実行させます。
それらの両方の例があります-LLVM(1つの明白な例のために)はほとんど前者を取ります。フロントエンドコンパイラはLLVMコードを発行し、LLVMはそれを最適化された実行可能ファイルに変換するために多くのインテリジェンス/作業を投入します。GIMPLEを使用するgccは、後者のルートを取ります。GIMPLEレコードは、基本的に、多数のオブジェクトファイルのビットをコンパイラにフィードバックし、コンパイラに最適化させてから、結果をリンカーにフィードバックするのに十分な情報をリンカーに提供します。実際に実行可能ファイルにコピーします。
おそらく、これら2つは基本的に同等であるという哲学的な見方を思いつくことができると思いますが、両方を実装した人なら誰でも同意するのではないかと思います。
さて、(おそらく、とにかく)これらのいずれかが手元の最適化を実装するのに十分であることは事実です。個人的には、この最適化を自分のために実装している人はいないと思います。あなたがそれに取り掛かるとき、qsort
そしてbsearch
それが通常適用される/通常適用されるであろうほとんど唯一の合理的に一般的な機能です。ほとんどの実用的な目的では、それはあなたがのためだけに最適化を実装することを意味しますqsort
。
一方、関連するツールにインライン関数とリンク時間の最適化を生成する機能が含まれている場合、この特定のタイプの最適化が多かれ少なかれ偶然の側面として発生する可能性が少なくとも合理的にあると思います。 2つが一緒になる効果。
少なくとも理論的には、それはそれが起こる可能性があることを意味します。ただし、考慮すべきもう1つの問題があります。手元の最適化とは完全に独立しているため、多くのコンパイラは再帰関数のインラインコードを生成しません。それを試みるためにも、コンパイラは最初に再帰関数を反復形式に変換する必要があります。これは末尾再帰の場合にはかなり一般的ですが、クイックソートは末尾再帰ではありません。ほぼ唯一の選択肢は、qsort
最初から再帰的ではない実装です。それは確かに可能ですが、確かにかなり珍しいことです。
そのため、ツールチェーンがコールバックのインライン生成をサポートできる場合でも、おそらくそうではありませんqsort
(これは、私が個人的にテストした唯一のケースです)。ただし、良くも悪くも、qsort
この種の機能のうち、どちらかが重要になるほど一般的なのはほぼ唯一の機能です。