मेरे पास एक ऐसा फ़ंक्शन है जो किसी दिए गए पूर्णांक के लिए दो की अगली शक्ति पाता है। यदि पूर्णांक दो की शक्ति है तो यह शक्ति देता है।सी ++ कंपाइलर "if (test) --foo" को "foo - = test" को अनुकूलित करने में विफल क्यों होता है?
सुंदर सीधे आगे:
char nextpow2if(int a)
{
char foo = char(32 - __builtin_clz(a));
bool ispow2 = !(a & a-1);
if (ispow2) --foo;
return foo;
}
हालांकि, -O2 साथ जीसीसी 6 के साथ संकलन उत्पन्न विधानसभा निरीक्षण के बाद के बाद, मुझे लगता है कि इस foo-1 की गणना के बाद प्रतीत होता है बेकार अनुदेश cmovne
साथ संकलित किया गया है। जीसीसी 5 और उससे अधिक उम्र के साथ भी बदतर मुझे कोड में वास्तविक jne
शाखा मिलती है।
इस रूप में अगर मैं निम्नलिखित समारोह लिखा था होगा संकलित करने के लिए तेजी से रास्ता:
char nextpow2sub(int a)
{
char foo = char(32 - __builtin_clz(a));
bool ispow2 = !(a & a-1);
return foo - ispow2;
}
इस कोड को सही ढंग से कम से कम (और सबसे तेजी से) एक sete
और घटाव के साथ संभव विधानसभा के लिए सभी compilers द्वारा संकलित किया गया है बूल के लिए।
संकलक पहले को अनुकूलित करने में विफल क्यों होता है? यह पहचान मामले के लिए वास्तव में आसान लगता है। जीसीसी 5 और पुराने क्यों इसे वास्तविक jne
शाखा में संकलित करते हैं? क्या दो संस्करणों के बीच कोई बढ़िया मामला है, जिसे मैं नहीं देख सकता, जिससे वे अलग-अलग व्यवहार कर सकते हैं?
पुनश्च: लाइव डेमो here
संपादित करें: मैं जीसीसी 6 के साथ लेकिन जीसीसी 5 के साथ बाद के बारे में दो गुना तेजी से (अच्छी तरह से एक कृत्रिम performanse परीक्षण पर, कम से कम) है प्रदर्शन का परीक्षण नहीं किया। यही कारण है कि वास्तव में मुझे इस सवाल पूछने के लिए प्रेरित किया।
असंबद्ध भाषाओं के लिए स्पैम टैग न करें! – Olaf
* "इसे संकलित करने का तेज़ तरीका ऐसा होगा जैसे मैंने निम्न कार्य लिखा था:" * क्या आपने इसे माप लिया? यह कितना तेज़ है? –
क्या आप उत्पन्न असेंबली कोड की संख्या से प्रदर्शन की तुलना कर रहे हैं? यह करने का यह एक अच्छा तरीका नहीं है (हालांकि यह कुछ मामलों में सच हो सकता है)। – Arunmu