__restrict__とインライン展開を用いてCコンパイラのalias analysisを回避する方法
コンパイラ依存ですが、__restrict__ とインライン展開を組み合わせることで、単一の値から派生したふたつのポインタを、互いに相互作用がないかのように最適化させることができます。たとえば以下のコードをコンパイルすると、
extern void f(int* sp); extern bool g(int* sp); struct frame_t { int x; }; inline bool _g(frame_t& __restrict__ frame, int* __restrict__ sp) __attribute__((always_inline)); bool _g(frame_t& __restrict__ frame, int* __restrict__ sp) { frame.x = 123; f(sp); return frame.x == 123; // この条件式は常に true と判定される } bool g(int* sp) { sp -= sizeof(frame_t) / sizeof(int); frame_t& frame = *reinterpret_cast<frame_t*>(sp); return _g(frame, sp); }
関数 bool g(int*) は、以下のようにコンパイルされます。返り値が即値 (true) に折りたたまれていることがわかります。
__Z1gPi: @ BB#0: push {r7, lr} movs r1, #123 mov r7, sp str r1, [r0, #-4]! blx __Z1fPi movs r0, #1 pop {r7, pc}
上記の例からも分かるかと思いますが、この種の最適化は GC を実装している場合などに効いてくると思います。
なお、本最適化が有効なことは Xcode 4.6 に付属する clang, g++ および llvm の trunk で確認しました。一方 gcc 4.7.2 では、ここで述べたような定数畳み込みは行われませんでした。