2016-06-22 4 views
6

है आंशिक रूप से पाश unrolling, यह पाश दस बार unrolls और फिर एक सशर्त कूद करताजीसीसी 5.1 लूप unrolling

-x c -std=c99 -O3 -funroll-all-loops --param max-completely-peeled-insns=1000 --param max-completely-peel-times=10000 

साथ जीसीसी 5.1 या बाद का उपयोग को देखते हुए निम्नलिखित कोड

#include <stdio.h> 

int main(int argc, char **argv) 
{ 
    int k = 0; 
    for(k = 0; k < 20; ++k) 
    { 
    printf("%d\n", k) ; 
    } 
} 

। इस तरह के 4.9.2 के रूप में जीसीसी के

.LC0: 
     .string "%d\n" 
main: 
     pushq %rbx 
     xorl %ebx, %ebx 
.L2: 
     movl %ebx, %esi 
     movl $.LC0, %edi 
     xorl %eax, %eax 
     call printf 
     leal 1(%rbx), %esi 
     movl $.LC0, %edi 
     xorl %eax, %eax 
     call printf 
     leal 2(%rbx), %esi 
     movl $.LC0, %edi 
     xorl %eax, %eax 
     call printf 
     leal 3(%rbx), %esi 
     movl $.LC0, %edi 
     xorl %eax, %eax 
     call printf 
     leal 4(%rbx), %esi 
     movl $.LC0, %edi 
     xorl %eax, %eax 
     call printf 
     leal 5(%rbx), %esi 
     movl $.LC0, %edi 
     xorl %eax, %eax 
     call printf 
     leal 6(%rbx), %esi 
     movl $.LC0, %edi 
     xorl %eax, %eax 
     call printf 
     leal 7(%rbx), %esi 
     movl $.LC0, %edi 
     xorl %eax, %eax 
     call printf 
     leal 8(%rbx), %esi 
     movl $.LC0, %edi 
     xorl %eax, %eax 
     call printf 
     leal 9(%rbx), %esi 
     xorl %eax, %eax 
     movl $.LC0, %edi 
     addl $10, %ebx 
     call printf 
     cmpl $20, %ebx 
     jne  .L2 
     xorl %eax, %eax 
     popq %rbx 
     ret 

लेकिन का उपयोग कर पुराने संस्करणों assemlby

.LC0: 
    .string "%d\n" 
main: 
    subq $8, %rsp 
    xorl %edx, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $1, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $2, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $3, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $4, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $5, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $6, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $7, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $8, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $9, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $10, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $11, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $12, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $13, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $14, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $15, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $16, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $17, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $18, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    movl $19, %edx 
    movl $.LC0, %esi 
    movl $1, %edi 
    xorl %eax, %eax 
    call __printf_chk 
    xorl %eax, %eax 
    addq $8, %rsp 
    ret 

वांछित बनाता है वहाँ यह वही उत्पादन का उत्पादन करने के लिए जीसीसी के बाद के संस्करणों के लिए मजबूर करने के लिए एक तरीका है?

https://godbolt.org/g/D1AR6i का उपयोग करते हुए विधानसभा का उत्पादन करने के

संपादित करें: कोई डुप्लिकेट किए गए सवाल के बाद से समस्या को पूरी तरह से जीसीसी के बाद के संस्करणों के साथ छोरों उतारना करने के लिए अभी तक हल नहीं किया गया है। पासिंग --param max-completely-peeled-insns=1000 --param max-completely-peel-times=10000 पर नहीं असर पड़ता है उत्पन्न विधानसभा का उपयोग कर जीसीसी> = 5.1

+1

दिलचस्प बात यह है कि यदि आप शर्त के लिए बदलते हैं, उदाहरण के लिए, 'के <9' अनलोल बिल्कुल नहीं किया जाता है ... – LPs

+0

@LPS बहुत छोटे पुनरावृत्ति को छोड़कर 2 या 3 – Garf365

+0

@ एलपी का उपयोग कर जीसीसी 4.9.2 अनोलिंग भी 9 से कम पुनरावृत्तियों के लिए काम करता है https://godbolt.org/g/ZPlCP6 – surrz

उत्तर

4

झंडे और मापदंडों का उपयोग कर रहे कि छोरों पूरी तरह से unrolled हो जाएगा गारंटी नहीं है।

(यानी पूरा छोरों की पुनरावृत्तियों की एक छोटे लगातार संख्या के साथ हटाने)

छीलने संकलक कि फैसला करती है तो पूरा पाश चालू हो जाती है: GCC documentation राज्यों -funroll-all-loops ध्वज प्रयोग कर रहे हैं के बारे में निम्नलिखित कोड के दिए गए टुकड़े के लिए पुनरावृत्तियों की संख्या "एक छोटा स्थिर" नहीं है (यानी संख्या बहुत अधिक है), यह केवल आंशिक छीलने या अनियंत्रित कर सकती है जैसा कि उसने यहां किया है। इसके अलावा, param विकल्प जो आप उपयोग कर रहे हैं केवल अधिकतम मान हैं, लेकिन सेट मान से छोटे लूप के लिए पूर्ण अनोलिंग को मजबूर नहीं करते हैं। दूसरे शब्दों में, यदि आपके पास सेट किए गए अधिकतम से अधिक लूप में अधिक पुनरावृत्ति है, तो लूप पूरी तरह से अनलॉक नहीं किया जाएगा; लेकिन उलटा सच नहीं है।

कई कारक ऑप्टिमाइज़ेशन करते समय ध्यान में रखे जाते हैं। यहां आपके कोड में बाधा printf फ़ंक्शन पर कॉल है, और संकलक शायद इसकी लागत गणना करते समय इसे ध्यान में रखेगा, या यह निर्णय लेगा कि अनियंत्रण के लिए निर्देश आकार ओवरहेड बहुत महत्वपूर्ण है। चूंकि आप इसे लूप को अनलॉक करने के लिए कह रहे हैं, ऐसा लगता है कि प्रारंभिक लूप को 10 अनलोल और एक कूद के साथ बदलने का सबसे अच्छा समाधान है।

यदि आप printf को किसी और चीज़ के साथ प्रतिस्थापित करते हैं, तो संकलक अलग-अलग अनुकूलित कर सकता है। उदाहरण के लिए निम्नलिखित इसकी जगह का प्रयास करें:

volatile int temp = k; 

इस नए कोड स्निपेट के साथ पाश पूरी तरह से unrolled नए जीसीसी के संस्करणों पर (और पुराने लोगों के साथ-साथ) हो जाएगा। ध्यान दें कि अस्थिर कीवर्ड केवल एक चाल है, इसलिए संकलक पूरी तरह से लूप को अनुकूलित नहीं करता है।

मेरे ज्ञान के सर्वोत्तम होने के लिए, जीसीसी के बाद के संस्करणों को उसी आउटपुट का उत्पादन करने के लिए मजबूर करने का कोई तरीका नहीं है।


एक तरफ ध्यान दें के रूप में, अनुकूलन स्तर -O2 के बाद और किसी भी अतिरिक्त संकलक झंडे के बिना से, बजना के हाल के संस्करणों पूरी तरह से अपने पाश उतारना।