Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/224.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何影响Android/ARM目标的Delphi XEx代码生成?_Android_Delphi_Android Ndk_Arm_Llvm - Fatal编程技术网

如何影响Android/ARM目标的Delphi XEx代码生成?

如何影响Android/ARM目标的Delphi XEx代码生成?,android,delphi,android-ndk,arm,llvm,Android,Delphi,Android Ndk,Arm,Llvm,更新日期2017-05-17。我不再为提出此问题的公司工作,也无法访问Delphi XEx。当我在那里的时候,通过迁移到混合FPC+GCC(Pascal+C)解决了这个问题,在一些例程中使用了NEON intrinsic,这会带来不同。(强烈建议使用FPC+GCC,因为它支持使用标准工具,特别是Valgrind。)如果有人能够用可信的示例演示他们如何从Delphi XEx生成优化的ARM代码,我很乐意接受答案 Embarcadero的Delphi编译器使用LLVM后端为Android设备生成本

更新日期2017-05-17。我不再为提出此问题的公司工作,也无法访问Delphi XEx。当我在那里的时候,通过迁移到混合FPC+GCC(Pascal+C)解决了这个问题,在一些例程中使用了NEON intrinsic,这会带来不同。(强烈建议使用FPC+GCC,因为它支持使用标准工具,特别是Valgrind。)如果有人能够用可信的示例演示他们如何从Delphi XEx生成优化的ARM代码,我很乐意接受答案


Embarcadero的Delphi编译器使用LLVM后端为Android设备生成本机ARM代码。我有大量的Pascal代码需要编译成Android应用程序,我想知道如何让Delphi生成更高效的代码。现在,我甚至没有谈论诸如自动SIMD优化之类的高级功能,只是谈论生成合理的代码。肯定有办法将参数传递到LLVM端,或者以某种方式影响结果?通常,任何编译器都会有许多选项来影响代码编译和优化,但Delphi的ARM目标似乎只是“优化开/关”,仅此而已

LLVM应该能够生成相当紧凑和合理的代码,但Delphi似乎以一种奇怪的方式使用它的工具。Delphi希望大量使用堆栈,它通常只使用处理器的寄存器r0-r3作为临时变量。也许最疯狂的是,它似乎将普通的32位整数加载为四个1字节的加载操作。如何让Delphi生成更好的ARM代码,而不必为Android带来逐字节的麻烦

起初,我认为逐字节加载是为了从big-endian交换字节顺序,但事实并非如此,它实际上只是加载一个32位的数字和4个单字节加载。*可能是加载完整的32位,而不进行未对齐的字大小内存加载。(是否应该避免这是另一回事,这将暗示整个事情是一个编译器错误)*

让我们看看这个简单的函数:

函数ReadInteger(APInteger:PInteger):整数;
开始
结果:=APInteger^;
结束;
即使启用了优化,Delphi XE7和update pack 1以及XE6也会为该功能生成以下ARM汇编代码:

section.text.的反汇编。\u ZN16Uarmcodetestform11ReadIntegerEPi:
00000000 :
0:b580推送{r7,lr}
2:466f mov r7,sp
4:b083子sp,#12
6:9002 str r0[sp,#8]
8:78c1 ldrb r1[r0,#3]
a:7882 ldrb r2[r0,#2]
c:ea42 2101或w r1、r2、r1、lsl#8
10:7842 ldrb r2[r0,#1]
12:7803 ldrb r3,[r0,#0]
14:ea43 2202或w r2、r3、r2、lsl#8
18:ea42 4101或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添加sp,#12
24:bd80 pop{r7,pc}
只需计算Delphi需要的指令数和内存访问数。从4个单字节加载中构造一个32位整数。。。如果我稍微更改一下函数并使用var参数而不是指针,它的复杂度会稍微低一些:

section.text.的反汇编。\u ZN16Uarmcodetestform14ReadIntegerVarERi:
00000000 :
0:b580推送{r7,lr}
2:466f mov r7,sp
4:b083子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添加sp,#12
12:bd80 pop{r7,pc}
这里我不包括反汇编,但对于iOS,Delphi为指针和var参数版本生成相同的代码,它们与Android var参数版本几乎相同,但并不完全相同。 编辑:为了澄清,逐字节加载只在Android上进行。而且只有在Android上,指针和var参数的版本才有所不同。在iOS上,两个版本生成完全相同的代码

为了进行比较,以下是FPC 2.7.1(2014年3月的SVN trunk版本)对优化级别为O2的功能的看法。指针和var参数版本完全相同

section.text.n\u p$armcodetest\u$$\ u readinteger$pinteger$$longint的反汇编:
00000000 :
0:6800 ldr r0,[r0,#0]
2:46f7移动pc,左后
我还使用Android NDK附带的C编译器测试了一个等效的C函数

int ReadInteger(int*APInteger)
{
返回*APInteger;
}
这与FPC制造的基本相同:

section.text的反汇编。_z11readingerpi:
00000000 :
0:6800 ldr r0,[r0,#0]
2:4770 bx lr
我们正在调查这个问题。简言之,它取决于指针引用的整数的潜在错误对齐(到32边界)。需要多一点时间才能得到所有答案。。。以及解决这一问题的计划

Marco Cantù,会议主持人

另请参考,因为Win64库在出厂时未进行优化


在QP报告中,Marco添加了以下解释:

这里有多个问题:

  • 如前所述,优化设置仅适用于整个单元文件,而不适用于单个函数。简单地说,在同一个文件中打开和关闭优化将没有效果
  • 此外,只需启用“调试信息”即可关闭优化。因此,在调试时,显式地启用优化不会产生任何效果。因此,IDE中的CPU视图将无法显示优化代码的反汇编视图
  • 第三,加载未对齐的64位数据不是一个简单的过程