__SHA__
이 정의되지 않은 경우 인라인 어셈블리를 사용하여 SHA 명령어를 사용할 수 있도록합니다. GCC에서 우리는 사용Clang에서 Yz 기계 제약이 부족한 곳에서 작업 하시겠습니까?
GCC_INLINE __m128i GCC_INLINE_ATTRIB
MM_SHA256RNDS2_EPU32(__m128i a, const __m128i b, const __m128i c)
{
asm ("sha256rnds2 %2, %1, %0" : "+x"(a) : "xm"(b), "Yz" (c));
return a;
}
연타 소비하지 않는 GCC의 Yz
constraint (Clang 3.2 Issue 13199 및 Clang 3.9 Issue 32727를 참조) sha256rnds2
명령에 의해 요구되는 :
Yz First SSE register (%xmm0).
우리는 연타에 대한 mov
추가 :
asm ("mov %2, %%xmm0; sha256rnds2 %%xmm0, %1, %0" : "+x"(a) : "xm"(b), "x" (c) : "xmm0");
성능이 바이트 당 약 3 사이클 씩 감소합니다. 내 2.2 GHz Celeron J3455 테스트 머신 (SHA 확장 기능이있는 Goldmont)은 약 230 MiB/s입니다. 그것의 사소한. 해체 보면
는 연타 주변에 최적화되지 않은 SHA의k
두 라운드 수행 할 때 :
예를 들어
Breakpoint 2, SHA256_SSE_SHA_HashBlocks (state=0xaaa3a0,
data=0xaaa340, length=0x40) at sha.cpp:1101
1101 STATE1 = _mm_loadu_si128((__m128i*) &state[4]);
(gdb) disass
Dump of assembler code for function SHA256_SSE_SHA_HashBlocks(unsigned int*, unsigned int const*, unsigned long):
0x000000000068cdd0 <+0>: sub $0x308,%rsp
0x000000000068cdd7 <+7>: movdqu (%rdi),%xmm0
0x000000000068cddb <+11>: movdqu 0x10(%rdi),%xmm1
...
0x000000000068ce49 <+121>: movq %xmm2,%xmm0
0x000000000068ce4d <+125>: sha256rnds2 %xmm0,0x2f0(%rsp),%xmm1
0x000000000068ce56 <+134>: pshufd $0xe,%xmm2,%xmm3
0x000000000068ce5b <+139>: movdqa %xmm13,%xmm2
0x000000000068ce60 <+144>: movaps %xmm1,0x2e0(%rsp)
0x000000000068ce68 <+152>: movq %xmm3,%xmm0
0x000000000068ce6c <+156>: sha256rnds2 %xmm0,0x2e0(%rsp),%xmm2
0x000000000068ce75 <+165>: movdqu 0x10(%rsi),%xmm3
0x000000000068ce7a <+170>: pshufb %xmm8,%xmm3
0x000000000068ce80 <+176>: movaps %xmm2,0x2d0(%rsp)
0x000000000068ce88 <+184>: movdqa %xmm3,%xmm4
0x000000000068ce8c <+188>: paddd 0x6729c(%rip),%xmm4 # 0x6f4130
0x000000000068ce94 <+196>: movq %xmm4,%xmm0
0x000000000068ce98 <+200>: sha256rnds2 %xmm0,0x2d0(%rsp),%xmm1
...
, 0068ce8c
0068ce98
불구하고 있었어야 : 나는 추측하고있어
paddd 0x6729c(%rip),%xmm0 # 0x6f4130
sha256rnds2 %xmm0,0x2d0(%rsp),%xmm1
우리가 선택한 인라인 asm 명령어는 약간 떨어져 있습니다.
우리는 어떻게기계 제약 조건의 부족을 해결하기 위해 Clang? 최적화 된 코드에서 중간 이동을 피하는 패턴은 무엇입니까? Explicit Register Variable를 사용하려고
:
const __m128i k asm("xmm0") = c;
asm ("sha256rnds2 %2, %1, %0" : "+x"(a) : "xm"(b), "x" (k));
return a;
결과 :
In file included from sha.cpp:24:
./cpu.h:831:22: warning: ignored asm label 'xmm0' on automatic variable
const __m128i k asm("xmm0") = c;
^
./cpu.h:833:7: error: invalid operand for instruction
asm ("sha256rnds2 %2, %1, %0" : "+x"(a) : "xm"(b), "x" (k));
^
<inline asm>:1:21: note: instantiated into assembly here
sha256rnds2 %xmm1, 752(%rsp), %xmm0
^~~~~~~~~~
In file included from sha.cpp:24:
./cpu.h:833:7: error: invalid operand for instruction
asm ("sha256rnds2 %2, %1, %0" : "+x"(a) : "xm"(b), "x" (k));
^
<inline asm>:1:21: note: instantiated into assembly here
sha256rnds2 %xmm3, 736(%rsp), %xmm1
^~~~~~~~~~
...
감사합니다. GCC는 [Explicit Register Variables] (https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables)를 호출합니다. Clang은 컴파일하지 않습니다. C++과 C 캐스트를 사용하여 여러 가지 방법을 시도했습니다. 나는 그것이'__m128i' 타입과 관련이 있다고 생각합니다. – jww
업데이트를 보면 명시 적 레지스터를 사용해야하는 임시 변수에 'register' 유형 한정자가 없습니다. 'register const __m128i k asm ("xmm0") = c;'시도해보십시오. –
Michael 감사합니다. 'register' 키워드는 C++에서 없어져서 사용할 수 없습니다. (우리는 C++ 라이브러리이며,이 코드는 헤더 파일에 있습니다. 아마도 __register 또는 GCC_REGISTER와 같은 컴파일러 특정 해결 방법을 찾아야 할 수도 있습니다). – jww