तो मैं जीसीसी में O3
पर कुछ जादू देख रहा हूं (वास्तव में मैं क्लैंग का उपयोग कर संकलन कर रहा हूं लेकिन यह जीसीसी के साथ समान है और मैं अनुमान लगा रहा हूं कि ऑप्टिमाइज़र का एक बड़ा हिस्सा जीसीसी से खींच लिया गया था क्लैंग करने के लिए)।एक कंपाइलर इस फैक्टोरियल फ़ंक्शन को कितनी अच्छी तरह अनुकूलित करता है?
इस सी कार्यक्रम पर विचार करें:
int foo(int n) {
if (n == 0) return 1;
return n * foo(n-1);
}
int main() {
return foo(10);
}
पहली बात मैं सुंदर वाह-एड (जो भी इस प्रश्न में वाह-एड था - https://stackoverflow.com/a/414774/1068248) था कैसे int foo(int)
(एक बुनियादी भाज्य समारोह) compiles एक तंग पाश में। यह इसके लिए एआरएम असेंबली है:
.globl _foo
.align 2
.code 16
.thumb_func _foo
_foo:
mov r1, r0
movs r0, #1
cbz r1, LBB0_2
LBB0_1:
muls r0, r1, r0
subs r1, #1
bne LBB0_1
LBB0_2:
bx lr
ब्लिमी मैंने सोचा। यह बहुत दिलचस्प है! फैक्टोरियल करने के लिए पूरी तरह से तंग लूपिंग। वाह। यह पूंछ कॉल अनुकूलन नहीं है, ठीक है, यह पूंछ कॉल नहीं है। लेकिन ऐसा लगता है कि यह एक बहुत ही अनुकूल अनुकूलन किया है।
अब main
को देखो:
.globl _main
.align 2
.code 16
.thumb_func _main
_main:
movw r0, #24320
movt r0, #55
bx lr
कि सिर्फ मेरे मन विस्फोट से उड़ा दिया ईमानदार होना। यह पूरी तरह से foo
को छोड़कर 3628800
लौटा रहा है जो 10!
है।
इससे मुझे वास्तव में एहसास हो जाता है कि आपका कंपाइलर अक्सर आपके कोड को अनुकूलित करने के लिए बेहतर काम कर सकता है। लेकिन यह सवाल उठाता है, यह अच्छी नौकरी कैसे प्रबंधित करता है? तो, किसी को समझा सकता है कि निम्नलिखित अनुकूलन काम (संभवतः प्रासंगिक कोड से लिंक करके):
प्रारंभिक
foo
अनुकूलन एक तंग पाश किया जाना है।अनुकूलन जहां
main
वास्तव मेंfoo
निष्पादित करने के बजाय सीधे परिणाम देता है और परिणाम देता है।
इसके अलावा इस सवाल का एक और दिलचस्प पक्ष प्रभाव कुछ और अधिक दिलचस्प अनुकूलन जो जीसीसी/बजना क्या कर सकते हैं दिखाने के लिए किया जाएगा।
उत्कृष्ट जवाब! और हां 'मुख्य' अनुकूलन वास्तव में केवल स्थिरांक के साथ प्रतिस्थापित किया जा सकता है ताकि एक साथ आसान हो। मुझे 'foo' अनुकूलन :-) के माध्यम से अपना चलना पसंद है। – mattjgalloway