整数の範囲を指定してオプティマイザにヒントを与えることはできますか? 質問する

整数の範囲を指定してオプティマイザにヒントを与えることはできますか? 質問する

値を格納するために型を使用していますint。プログラムのセマンティクスにより、値は常に非常に狭い範囲 (0 - 36) で変化し、 CPU 効率のためだけにint(not a char) が使用されます。

このような狭い範囲の整数に対して、多くの特殊な算術最適化を実行できるようです。これらの整数に対する多くの関数呼び出しは、小さな「魔法の」操作セットに最適化される可能性があり、一部の関数はテーブル検索に最適化される可能性もあります。

では、これが常にその狭い範囲内にあることをコンパイラに伝えint、コンパイラがそれらの最適化を行うことは可能でしょうか?

ベストアンサー1

はい、可能です。たとえば、次のようにして、不可能な条件をコンパイラーに通知するgccことができます。__builtin_unreachable

if (value < 0 || value > 36) __builtin_unreachable();

上記の条件をマクロでラップすることができます。

#define assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)

次のように使用します:

assume(x >= 0 && x <= 10);

ご覧のようには、gccこの情報に基づいて最適化を実行します。

#define assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)

int func(int x){
    assume(x >=0 && x <= 10);

    if (x > 11){
        return 2;
    }
    else{
        return 17;
    }
}

生産:

func(int):
    mov     eax, 17
    ret

しかし、欠点はコードがそのような仮定を破った場合、未定義の動作が発生します。

デバッグ ビルドであっても、これが発生したときに通知されません。仮定を使用してバグをより簡単にデバッグ/テスト/キャッチするには、次のように、ハイブリッドの assert/assert マクロ (クレジットは @David Z 氏) を使用できます。

#if defined(NDEBUG)
#define assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
#else
#include <cassert>
#define assume(cond) assert(cond)
#endif

デバッグビルド(NDEBUG ない定義されている場合、通常の のように動作しassert、エラー メッセージを出力してabortプログラムを し、リリース ビルドでは仮定を使用して最適化されたコードを生成します。

ただし、これは通常の代替ではないことに注意してください。assert-condはリリース ビルドに残るので、 のようなことは行わないでくださいassume(VeryExpensiveComputation())

おすすめ記事