LLVMでSSE組み込み関数を使う

現在LLVMがマイブームである。今日ふと思い立ってSSE組み込み関数が含まれたC++のコードがllvm-g++でどのように変換されるのか試してみた。元のC++ソースコードは以下の通り。

#include <nmmintrin.h> 

void add(float* x, float* y, float*z) {
	_mm_storeu_ps(z, _mm_add_ps(_mm_loadu_ps(x), _mm_loadu_ps(y)));
}

そして変換後のLLVMのコードが以下の通り。

; ModuleID = 'sse.cpp'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
target triple = "i386-mingw32"

define void @_Z3addPfS_S_(float* %x, float* %y, float* %z) nounwind {
entry:
  %0 = bitcast float* %y to i8*                   ; <i8*> [#uses=1]
  %1 = tail call <4 x float> @llvm.x86.sse.loadu.ps(i8* %0) nounwind readonly ; <<4 x float>> [#uses=1]
  %2 = bitcast float* %x to i8*                   ; <i8*> [#uses=1]
  %3 = tail call <4 x float> @llvm.x86.sse.loadu.ps(i8* %2) nounwind readonly ; <<4 x float>> [#uses=1]
  %tmp.i = fadd <4 x float> %3, %1                ; <<4 x float>> [#uses=1]
  %4 = bitcast float* %z to i8*                   ; <i8*> [#uses=1]
  tail call void @llvm.x86.sse.storeu.ps(i8* %4, <4 x float> %tmp.i) nounwind
  ret void
}

declare <4 x float> @llvm.x86.sse.loadu.ps(i8*) nounwind readonly

declare void @llvm.x86.sse.storeu.ps(i8*, <4 x float>) nounwind

_mm_loadu_ps()等が組み込み関数やベクトル演算に変換されているのがわかる。さすがLLVMだ。