2017-05-17 को अपडेट करें। मैं अब उस कंपनी के लिए काम नहीं करता जहां यह प्रश्न उत्पन्न हुआ है, और डेल्फी एक्सएक्सएक्स तक पहुंच नहीं है। जब मैं वहां था, समस्या को मिश्रित एफपीसी + जीसीसी (पास्कल + सी) में माइग्रेट करके हल किया गया था, जहां कुछ रूटीन के लिए नियॉन इंट्रिंसिक्स के साथ इसमें अंतर हुआ। (FPC + GCC की अत्यधिक अनुशंसा की जाती है क्योंकि यह मानक उपकरण, विशेष रूप से Valgrind का उपयोग करने में सक्षम बनाता है।) यदि कोई व्यक्ति विश्वसनीय उदाहरणों के साथ प्रदर्शित कर सकता है, तो वे वास्तव में डेल्फी एक्सएक्सएक्स से अनुकूलित एआरएम कोड का उत्पादन कैसे कर सकते हैं, मुझे उत्तर स्वीकार करने में खुशी हो रही है। ।
Embarcadero के डेल्फी कंपाइलर Android उपकरणों के लिए देशी ARM कोड बनाने के लिए LLVM बैकएंड का उपयोग करते हैं। मेरे पास बड़ी मात्रा में पास्कल कोड हैं जिन्हें मुझे एंड्रॉइड एप्लिकेशन में संकलित करने की आवश्यकता है और मैं यह जानना चाहूंगा कि डेल्फी को अधिक कुशल कोड कैसे बनाया जाए। अभी, मैं स्वचालित सिमडी अनुकूलन जैसी उन्नत सुविधाओं के बारे में बात नहीं कर रहा हूं, बस उचित कोड के उत्पादन के बारे में। निश्चित रूप से एलएलवीएम पक्ष के मापदंडों को पारित करने का एक तरीका होना चाहिए, या किसी तरह परिणाम को प्रभावित करना चाहिए? आमतौर पर, किसी भी संकलक के पास कोड संकलन और अनुकूलन को प्रभावित करने के लिए कई विकल्प होंगे, लेकिन डेल्फी के एआरएम लक्ष्य सिर्फ "अनुकूलन / बंद" और ऐसा लगता है।
LLVM यथोचित तंग और समझदार कोड का उत्पादन करने में सक्षम माना जाता है, लेकिन ऐसा लगता है कि डेल्फी अपनी सुविधाओं का उपयोग एक अजीब तरीके से कर रहा है। डेल्फी स्टैक का बहुत अधिक उपयोग करना चाहता है, और यह आमतौर पर प्रोसेसर के रजिस्टरों r0-r3 का उपयोग अस्थायी चर के रूप में करता है। शायद सभी का पागलपन, यह चार 1-बाइट लोड संचालन के रूप में सामान्य 32 बिट पूर्णांक लोड हो रहा है। डेल्फी को बेहतर एआरएम कोड का उत्पादन कैसे करें, और बाइट-बाय-बाइट की परेशानी के बिना यह एंड्रॉइड के लिए बना रहा है?
पहले मुझे लगा कि बाइट-बाइट लोडिंग बड़े-एंडियन से बाइट ऑर्डर को स्वैप करने के लिए थी, लेकिन ऐसा नहीं था, यह वास्तव में 4 सिंगल-बाइट लोड के साथ 32 बिट नंबर लोड करना है। * यह लोड करना हो सकता है। पूर्ण 32 बिट्स बिना किसी शब्द आकार के मेमोरी लोड किए बिना। (क्या यह बचना चाहिए कि एक और बात है, जो पूरी बात संकलक बग होने का संकेत देगा) *
आइए इस सरल कार्य को देखें:
function ReadInteger(APInteger : PInteger) : Integer;
begin
Result := APInteger^;
end;
यहां तक कि अद्यतन पैक 1 के साथ डेल्फी XE7, साथ ही साथ XE6 पर स्विच किए गए अनुकूलन के साथ, उस फ़ंक्शन के लिए निम्न एआरएम असेंबली कोड का उत्पादन करें:
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 पैरामीटर संस्करण एक दूसरे से भिन्न होते हैं। IOS पर दोनों वर्जन बिलकुल समान कोड जनरेट करते हैं।
तुलना के लिए, यहां FPC 2.7.1 (मार्च 2014 से 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;
}
और यह अनिवार्य रूप से उसी चीज को संकलित करता है जिसे एफपीसी ने बनाया है:
Disassembly of section .text._Z11ReadIntegerPi:
00000000 <_Z11ReadIntegerPi>:
0: 6800 ldr r0, [r0, #0]
2: 4770 bx lr
armeabi-v7a
इसके बजाय लक्ष्यीकरण का निर्माण किया है armeabi
(यह सुनिश्चित नहीं है कि इस संकलक में ऐसे विकल्प हैं), चूंकि ARMv6 (जबकि armeabi
ARMv5 को मानता है) के बाद अनलग्टेड लोड का समर्थन किया जाना चाहिए । (दिखाया गया डिस्सैम्ड ऐसा नहीं लगता है कि यह एक बिगेंडियन वैल्यू पढ़ता है, यह सिर्फ एक बार में एक छोटे से बाइट मूल्य को पढ़ता है।)