__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 では、ここで述べたような定数畳み込みは行われませんでした。