2015-07-23 4 views
6

यह How to force const propagation through an inline function? से संबंधित है Clang एक एकीकृत असेंबलर है; और यह सिस्टम के असेंबलर का उपयोग नहीं करता है (जो अक्सर जीएनयू एएस (जीएएस) होता है)। गैर-क्लैंग ने गणित को जल्दी प्रदर्शन किया, और सब कुछ "अभी काम किया"।फोर्स क्लैंग निरंतर मानों पर "गणित प्रारंभिक" करने के लिए

मैं "प्रारंभिक" कहता हूं क्योंकि @ n.m। इसे "प्रीप्रोसेसर द्वारा प्रदर्शन गणित" के रूप में वर्णित करने के लिए विरोध किया। लेकिन विचार यह है कि मूल्य संकलन समय पर जाना जाता है, और इसे जल्दी मूल्यांकन किया जाना चाहिए, जैसे प्रीप्रोसेसर #if (X % 32 == 0) का मूल्यांकन करता है।

नीचे, क्लैंग 3.6 एक बाधा का उल्लंघन करने की शिकायत कर रहा है।

$ export CXX=/usr/local/bin/clang++ 
$ $CXX --version 
clang version 3.6.0 (tags/RELEASE_360/final) 
Target: x86_64-apple-darwin12.6.0 
... 
$ make 
/usr/local/bin/clang++ -DNDEBUG -g2 -O3 -Wall -fPIC -arch i386 -arch x86_64 -pipe -Wno-tautological-compare -c integer.cpp 
In file included from integer.cpp:8: 
In file included from ./integer.h:7: 
In file included from ./secblock.h:7: 
./misc.h:941:44: error: constraint 'I' expects an integer constant expression 
     __asm__ ("rolb %1, %0" : "+mq" (x) : "I" ((unsigned char)(y%8))); 
                ^~~~~~~~~~~~~~~~~~~~ 
./misc.h:951:44: error: constraint 'I' expects an integer constant expression 
... 

कार्यों ऊपर inlined कर रहे हैं टेम्पलेट विशेषज्ञताओं:: यह लगातार भर प्रचारित प्रकट होता है नहीं किया जा रहा

template<> inline byte rotrFixed<byte>(byte x, unsigned int y) 
{ 
    // The I constraint ensures we use the immediate-8 variant of the 
    // shift amount y. However, y must be in [0, 31] inclusive. We 
    // rely on the preprocessor to propoagte the constant and perform 
    // the modular reduction so the assembler generates the instruction. 
    __asm__ ("rorb %1, %0" : "+mq" (x) : "I" ((unsigned char)(y%8))); 
    return x; 
} 

वे एक स्थिरांक मान के साथ लागू किया जा रहा है, इसलिए घुमाने राशि संकलन समय पर जाना जाता है । एक ठेठ फोन करने वाले की तरह लग सकता है:

unsigned int x1 = rotrFixed<byte>(1, 4); 
unsigned int x2 = rotrFixed<byte>(1, 32); 

इन [संदिग्ध] चाल में से कोई भी अगर GCC या Clang एक आंतरिक rotate in near constant time प्रदर्शन करने के लिए प्रदान की आवश्यकता होगी। मैं "घुमावदार प्रदर्शन" के लिए भी व्यवस्थित हूं क्योंकि उनके पास यह भी नहीं है।

क्लैंग मूल्य के प्रीप्रोकैसिंग करने के लिए क्लैंग को फिर से शुरू करने के लिए आवश्यक चाल क्या है?


चतुर पाठकों rotrFixed<byte>(1, 32) पहचान लेंगे अपरिभाषित व्यवहार हो सकता है अगर एक पारंपरिक सी का उपयोग कर/C++ बारी बारी से। इसलिए हम सी/सी ++ सीमाओं से बचने के लिए असेंबली में उतरते हैं और 1 निर्देश गति का आनंद लेते हैं।

उत्सुक पाठक आश्चर्य कर सकता है कि हम ऐसा क्यों करेंगे। क्रिप्टोग्राफर्स चश्मे को बुलाते हैं, और कभी-कभी ये चश्मा अंतर्निहित हार्डवेयर या मानक निकायों से सहानुभूति नहीं रखते हैं। क्रिप्टोग्राफर के विनिर्देश को बदलने के बजाय, हम लेखापरीक्षा को आसान बनाने के लिए इसे क्रियात्मक प्रदान करने का प्रयास करते हैं।


इस समस्या के लिए एक बग खोला गया है: LLVM Bug 24226 - Constant not propagated into inline assembly, results in "constraint 'I' expects an integer constant expression"

मुझे नहीं पता कि क्लेंग क्या गारंटी देता है, लेकिन मुझे संकलक और एकीकृत असेंबलर का दावा जीसीसी और जीएनयू के असेंबलर के साथ संगत होने का दावा है। और जीसीसी और जीएएस निरंतर मूल्य का प्रचार प्रदान करते हैं।

+1

आप प्रीप्रोसेसर अंकगणितीय के बारे में बात करते रहते हैं, लेकिन आपके कोड में कहीं भी # परिभाषित स्थिरांक नहीं हैं। –

+0

आप सिस्टम असेंबलर का उपयोग '-no-integr-as'' के माध्यम से कर सकते हैं। – Thomas

+2

यदि 'y' comoile समय पर जाना जाता है, तो इसे टेम्पलेट पैरामीटर क्यों न बनाएं? –

उत्तर

2

जब से तुम भाग्य निर्णय डिजाइन की वजह से निरंतर मूल्यांकन के लिए मजबूर करने की कोशिश कर रहा से बाहर होने लगते हैं, ror r/m8, cl प्रपत्र एक अच्छा समझौता हो सकता है:

__asm__ ("rorb %b1, %b0" : "+q,m" (x) : "c,c" (y) : "cc"); 

कई विकल्प बाधा वाक्य रचना रजिस्टर 'को बढ़ावा देने' के लिए है क्लैंग के साथ किसी समस्या के कारण स्मृति उपयोग पर उपयोग करें, here को कवर किया गया। मुझे नहीं पता कि इस मुद्दे को बाद के संस्करणों में हल किया गया है या नहीं। जीसीसी बाधा मिलान और स्पिल से परहेज करने के लिए बेहतर होता है।

को rcx/ecx/cl रजिस्टर में लोड करने की आवश्यकता है, लेकिन संकलक शायद इसे किसी अन्य विलंबता के पीछे छिपा सकता है। इसके अलावा, (y) के लिए कोई सीमा समस्या नहीं है। rorb प्रभावी रूप से (%cl % 8) का उपयोग करता है।"cc" क्लॉबर की आवश्यकता नहीं है।


एक अभिव्यक्ति है निरंतर, दोनों जीसीसी और बजना __builtin_constant_p उपयोग कर सकते हैं:

if (__builtin_constant_p(y)) 
    __asm__("rorb %1, %b0" : "+q,m" (x) : "N,N" ((unsigned char) y) : "cc"); 
else 
    ... non-constant (y) ... 

या मेलिंग सूची में alluded के रूप में:

if (__builtin_constant_p(y)) 
{ 
    if ((y &= 0x7) != 0) 
     x = (x >> y) | (x << (8 - y)); /* gcc generates rotate. */ 
} 
+0

* "' rorb प्रभावी रूप से उपयोग करता है (% cl% 8) '" * - मुझे पता था कि इसका लाभ उठाया जा सकता है, लेकिन मुझे नहीं पता था कि इसे कैसे व्यक्त किया जाए ... धन्यवाद। – jww

+1

@jww - बीटीडब्लू, 8-बिट हस्ताक्षरित तत्काल तत्काल के लिए, आप '" I "के बजाय' "एन" 'बाधा का उपयोग कर सकते हैं, और रेंज मॉड्यूल 8 को 'ror' संभाल सकते हैं। –

0

तो 'एन' 8 बिट के लिए दबाव, फिर 16/32/64 के बारे में कैसे?

संबंधित मुद्दे