Win32 で GUI アプリケーションに C++builder を使用しています。Borland コンパイラの最適化は非常に悪く、SSE の使い方がわかりません。mingw gcc 4.7 でコンパイルすると 5 倍高速になる関数があります。Borland コンパイラではインライン アセンブラが許可されているため、gcc にアセンブラ コードを生成してから、C 関数内でこの cod を使用するように依頼することを考えています。
C の関数は次のようになります。
void Test_Fn(double *x, size_t n,double *AV, size_t *mA, size_t NT)
{
double s = 77.777;
size_t m = mA[NT-3];
AV[2]=x[n-4]+m*s;
}
質問を単純化するために、関数コードを非常に単純にしました。私の実際の機能には多くのループが含まれています。
Borland C++ コンパイラは、次のアセンブラ コードを生成しました。
;
; void Test_Fn(double *x, size_t n,double *AV, size_t *mA, size_t NT)
;
@1:
push ebp
mov ebp,esp
add esp,-16
push ebx
;
; {
; double s = 77.777;
;
mov dword ptr [ebp-8],1580547965
mov dword ptr [ebp-4],1079210426
;
; size_t m = mA[NT-3];
;
mov edx,dword ptr [ebp+20]
mov ecx,dword ptr [ebp+24]
mov eax,dword ptr [edx+4*ecx-12]
;
; AV[2]=x[n-4]+m*s;
;
?live16385@48: ; EAX = m
xor edx,edx
mov dword ptr [ebp-16],eax
mov dword ptr [ebp-12],edx
fild qword ptr [ebp-16]
mov ecx,dword ptr [ebp+8]
mov ebx,dword ptr [ebp+12]
mov eax,dword ptr [ebp+16]
fmul qword ptr [ebp-8]
fadd qword ptr [ecx+8*ebx-32]
fstp qword ptr [eax+16]
;
; }
;
?live16385@64: ;
@2:
pop ebx
mov esp,ebp
pop ebp
ret
gcc で生成されたアセンブラー コードは次のとおりです。
_Test_Fn:
mov edx, DWORD PTR [esp+20]
mov eax, DWORD PTR [esp+16]
mov eax, DWORD PTR [eax-12+edx*4]
mov edx, DWORD PTR [esp+8]
add eax, -2147483648
cvtsi2sd xmm0, eax
mov eax, DWORD PTR [esp+4]
addsd xmm0, QWORD PTR LC0
mulsd xmm0, QWORD PTR LC1
addsd xmm0, QWORD PTR [eax-32+edx*8]
mov eax, DWORD PTR [esp+12]
movsd QWORD PTR [eax+16], xmm0
ret
LC0:
.long 0
.long 1105199104
.align 8
LC1:
.long 1580547965
.long 1079210426
.align 8
gcc と Borland C++ で関数の引数へのアクセスがどのように行われるかについてのヘルプを得るのが好きです。Borland の C++ での私の関数は次のようになります。
void Test_Fn(double *x, size_t n,double *AV, size_t *mA, size_t NT)
{
__asm
{
put gcc generated assembler here
}
}
Borland はebp
、gcc がレジスタを使用している間にレジスタを使用し始めesp
ます。cdecl ou stdcall のようないくつかの呼び出し規則を使用して、引数にアクセスするための互換性のあるコードをコンパイラの 1 つに生成させることはできますか?