programing

Android/ARM 대상의 델파이 XEX 코드 생성에 어떤 영향을 미칠까요?

css3 2023. 10. 12. 23:23

Android/ARM 대상의 델파이 XEX 코드 생성에 어떤 영향을 미칠까요?

업데이트 2017-05-17.저는 이 질문이 시작된 회사에서 더 이상 근무하지 않으며, 델파이 XEX에 접속할 수 없습니다.제가 그곳에 있는 동안, 일부 루틴에 대해 NEON 고유의 기능을 사용하여 혼합 FPC+GCC(Pascal+C)로 마이그레이션하여 문제를 해결했습니다. (FPC+GCC는 표준 도구, 특히 Valgrind를 사용할 수 있기 때문에 매우 권장됩니다.)신뢰할 수 있는 사례를 통해 델파이 XEX에서 최적화된 ARM 코드를 실제로 만들어낼 수 있는 방법을 보여줄 수 있다면 기꺼이 답변을 받아들이겠습니다.


엠바카데로의 델파이 컴파일러는 LLVM 백엔드를 사용하여 안드로이드 장치용 네이티브 ARM 코드를 생성합니다.안드로이드 어플리케이션에 컴파일해야 하는 파스칼 코드가 많이 있는데 델파이에서 효율적인 코드를 생성할 수 있는 방법을 알고 싶습니다.지금은 자동 SIMD 최적화와 같은 고급 기능에 대해서도 이야기하지 않고 합리적인 코드를 만들어 내는 것에 대해서만 이야기하고 있습니다.분명 매개 변수를 LLVM 측에 전달할 방법이 있거나, 아니면 어떻게든 결과에 영향을 미치는 방법이 있어야 합니다.일반적으로 모든 컴파일러는 코드 컴파일 및 최적화에 영향을 미칠 수 있는 다양한 옵션을 가지고 있지만, 델파이의 ARM 목표는 "최적화 온/오프"에 불과한 것 같습니다.

LLVM은 상당히 엄격하고 합리적인 코드를 생성할 수 있어야 하는데, 델파이가 자사의 설비를 이상하게 사용하고 있는 것 같습니다.델파이는 스택을 매우 많이 사용하기를 원하며, 일반적으로 프로세서의 레지스터 r0-r3를 임시 변수로만 사용합니다.아마도 가장 말도 안 되는 것은 정상적인 32비트 정수를 4개의 1바이트 로드 작업으로 로드하는 것 같습니다.델파이가 어떻게 하면 더 나은 ARM 코드를 만들어 낼 수 있고, 그것이 바이트 단위의 번거로움 없이 안드로이드를 위해 만들어 낼 수 있을까요?

처음에는 바이트 단위로 로드하는 것이 빅엔디안에서 바이트 순서를 교환하기 위한 것이라고 생각했는데, 그렇지 않아서 실제로는 32비트 숫자에 싱글바이트 로드 4개를 로드하는 것입니다.* 정렬되지 않은 워드 크기의 메모리 로드 없이 전체 32비트를 로드하는 것일 수 있습니다.(이것은 전체가 컴파일러 버그임을 암시하는 또 다른 것입니다.)*

다음과 같은 간단한 기능을 살펴보겠습니다.

function ReadInteger(APInteger : PInteger) : Integer;
begin
  Result := APInteger^;
end;

최적화 기능을 켜더라도 업데이트 팩 1이 포함된 Dell XE7 및 XE6는 해당 기능에 대해 다음과 같은 ARM 어셈블리 코드를 생성합니다.

Disassembly of section .text._ZN16Uarmcodetestform11ReadIntegerEPi:

00000000 <_ZN16Uarmcodetestform11ReadIntegerEPi>:
   0:   b580        push    {r7, lr}
   2:   466f        mov r7, sp
   4:   b083        sub sp, #12
   6:   9002        str r0, [sp, #8]
   8:   78c1        ldrb    r1, [r0, #3]
   a:   7882        ldrb    r2, [r0, #2]
   c:   ea42 2101   orr.w   r1, r2, r1, lsl #8
  10:   7842        ldrb    r2, [r0, #1]
  12:   7803        ldrb    r3, [r0, #0]
  14:   ea43 2202   orr.w   r2, r3, r2, lsl #8
  18:   ea42 4101   orr.w   r1, r2, r1, lsl #16
  1c:   9101        str r1, [sp, #4]
  1e:   9000        str r0, [sp, #0]
  20:   4608        mov r0, r1
  22:   b003        add sp, #12
  24:   bd80        pop {r7, pc}

이를 위해 델파이에 필요한 명령과 메모리 액세스 횟수를 세어 보십시오.그리고 4개의 싱글바이트 로드로 32비트 정수를 구성하는 것은...함수를 조금 바꾸고 포인터 대신 var 매개 변수를 사용하면 약간 덜 복잡해집니다.

Disassembly of section .text._ZN16Uarmcodetestform14ReadIntegerVarERi:

00000000 <_ZN16Uarmcodetestform14ReadIntegerVarERi>:
   0:   b580        push    {r7, lr}
   2:   466f        mov r7, sp
   4:   b083        sub sp, #12
   6:   9002        str r0, [sp, #8]
   8:   6801        ldr r1, [r0, #0]
   a:   9101        str r1, [sp, #4]
   c:   9000        str r0, [sp, #0]
   e:   4608        mov r0, r1
  10:   b003        add sp, #12
  12:   bd80        pop {r7, pc}

여기에 디어셈블리를 포함하지는 않겠지만 iOS의 경우 델파이는 포인터 및 var 파라미터 버전에 대해 동일한 코드를 생성하며 안드로이드 var 파라미터 버전과 거의 동일하지는 않습니다.편집: 명확히 설명하자면, 바이트 단위 로딩은 안드로이드에서만 가능합니다. 그리고 안드로이드에서만 포인터와 var 파라미터 버전이 서로 다릅니다. iOS에서는 두 버전 모두 정확히 동일한 코드를 생성합니다.

비교를 위해 FPC 2.7.1(2014년 3월의 SVN 트렁크 버전)은 최적화 레벨 -O2의 기능에 대해 이렇게 생각합니다.포인터와 var 매개 변수 버전은 정확히 동일합니다.

Disassembly of section .text.n_p$armcodetest_$$_readinteger$pinteger$$longint:

00000000 <P$ARMCODETEST_$$_READINTEGER$PINTEGER$$LONGINT>:

   0:   6800        ldr r0, [r0, #0]
   2:   46f7        mov pc, lr

또한 안드로이드 NDK와 함께 제공되는 C 컴파일러와 동등한 C 기능을 테스트했습니다.

int ReadInteger(int *APInteger)
{
    return *APInteger;
}

그리고 이것은 FPC가 만든 것과 본질적으로 동일한 것으로 컴파일됩니다.

Disassembly of section .text._Z11ReadIntegerPi:

00000000 <_Z11ReadIntegerPi>:
   0:   6800        ldr r0, [r0, #0]
   2:   4770        bx  lr

우리는 그 문제를 조사하고 있습니다.즉, 포인터가 참조하는 정수의 잠재적 오정렬(32개 경계)에 따라 달라집니다.모든 답을 얻기 위해서는 시간이 좀 더 필요합니다.이 문제를 해결할 계획입니다

Marco Cant ù, Delphi Developers 담당 사회자

참고 항목 Delphi zlib 및 zip 라이브러리가 64비트 이하로 느린 이유는 무엇입니까? Win64 라이브러리는 최적화되지 않은 상태로 제공됩니다.


QP Report: RSP-9922 컴파일러가 만든 잘못된 ARM 코드 $O 디렉티브 무시?에서 마르코는 다음과 같은 설명을 덧붙였습니다.

여기에는 여러 가지 문제가 있습니다.

  • 그림과 같이, 최적화 설정은 전체 단위 파일에만 적용되며 개별 기능에는 적용되지 않습니다.간단히 말하면, 동일한 파일에서 최적화를 설정하거나 해제해도 효과가 없습니다.
  • 또한 단순히 "디버그 정보"를 활성화하면 최적화가 해제됩니다.따라서 디버깅할 때 최적화를 명시적으로 설정해도 효과가 없습니다.따라서 IDE의 CPU 뷰는 최적화된 코드의 분해된 뷰를 표시할 수 없습니다.
  • 셋째, 정렬되지 않은 64비트 데이터를 로드하는 것은 안전하지 않고 오류가 발생하므로 주어진 시나리오에서 필요한 별도의 4개의 1바이트 작업이 필요합니다.

언급URL : https://stackoverflow.com/questions/27946387/how-to-affect-delphi-xex-code-generation-for-android-arm-targets