2014-09-01 5 views
9

में फ़ंक्शन को इनलाइन करने के लिए मजबूर करें क्या क्लैंग/एलएलवीएम में इनलाइन फ़ंक्शन को मजबूर करने का कोई तरीका है?क्लैंग/एलएलवीएम

AFAIK, निम्नलिखित संकलक के लिए सिर्फ एक संकेत है लेकिन यह अनुरोध को अनदेखा कर सकता है।

__attribute__((always_inline)) 

मुझे कोई फर्क नहीं पड़ता कि संकलन विफल हो जाएगा यदि यह फ़ंक्शन इनलाइन नहीं कर सकता है।

उत्तर

9

सीएंड के साथ संकलन करते समय एक अच्छा समाधान है जो क्लेंग का डिफ़ॉल्ट है। इसका उपयोग बस इनलाइन विशेषता का उपयोग कर रहा है।

inline void foo() {} 

यह अच्छी तरह से Clang's compatibility page में लिखा है:

डिफ़ॉल्ट रूप से, बजना C99 मानक है, जो जीसीसी के डिफ़ॉल्ट व्यवहार से इनलाइन कीवर्ड के लिए अलग-अलग अर्थ विज्ञान प्रदान करता है के अनुसार सी कोड बनाता है ...

सी 99 में, इनलाइन का मतलब है कि फ़ंक्शन की परिभाषा केवल इनलाइनिंग के लिए प्रदान की जाती है, और प्रोग्राम में कहीं और परिभाषा (इनलाइन के बिना) है। इसका मतलब है कि यह प्रोग्राम अधूरा है, क्योंकि यदि जोड़ को रेखांकित नहीं किया गया है (उदाहरण के लिए, ऑप्टिमाइज़ेशन के बिना संकलन करते समय), तो मुख्य उस अन्य परिभाषा का एक अनसुलझा संदर्भ होगा। इसलिए हमें एक (सही) लिंक-टाइम त्रुटि मिलेगी ...

जीसीसी इसे एक एक्सटेंशन के रूप में पहचानता है और इसे ऑप्टिमाइज़र को संकेत के रूप में मानता है।

तो क्रम में गारंटी नहीं है कि समारोह inlined है:

  1. स्थिर इनलाइन प्रयोग न करें।
  2. उस फ़ंक्शन के लिए कोई अन्य कार्यान्वयन न जोड़ें जिसमें इनलाइन विशेषता नहीं है।
  3. आपको अनुकूलन का उपयोग करना होगा। लेकिन अगर अनुकूलन नहीं है तो भी संकलन विफल हो जाएगा जो अच्छा है।
  4. सुनिश्चित करें कि GNU89 के साथ संकलित न करें।
+0

'स्थिर इनलाइन' का उपयोग न करें? मुझे लगता है कि इस तरह से आपको क्लैंग में लिंक त्रुटि मिल जाएगी (क्योंकि इसका डिफ़ॉल्ट व्यवहार c99 है) –

+0

यह लिंकिंग में असफल हो सकता है अगर यह इनलाइन करने में असफल रहा (और फ़ंक्शन को स्थिर के रूप में घोषित नहीं किया गया था)। लेकिन यह इरादा है जैसा कि मैंने इस सवाल में लिखा था: "मुझे कोई फर्क नहीं पड़ता कि संकलन विफल हो जाएगा यदि यह फ़ंक्शन को रेखांकित नहीं कर सकता"। – DavidS

+0

ठीक है, मैं आपका विचार देखता हूं; आपने वास्तव में अपने प्रश्न का उत्तर दिया। हालांकि आपको थोड़ी अजीब आवश्यकता है :-) –

4

मैं क्लैंग/एलएलवीएम ढांचे के भीतर किसी भी उपकरण के लिए पूछने के रूप में आपके प्रश्न का इलाज करने जा रहा हूं। यहां मेरा सुझाव है: अपने कोड को एलएलवीएम बिटकोड में संकलित करें और फिर Always inline pass चलाएं।

उदाहरण के लिए:

> clang <other CFLAGS> -emit-llvm -c -o foo.bc foo.c 
> opt -always-inline foo.bc -o foo_inline.bc 
> clang -c -o foo.o foo_inline.bc 

मैंने पहले इस क्रम का इस्तेमाल किया है और यह inlined है मेरी कार्यों के सभी चिह्नित "always_inline"। मेरे मामले में, मैं पहले से ही अन्य विश्लेषण कर रहा था और बिटकोड पर बदलता था, इसलिए मुझे केवल चुनने के लिए ध्वज जोड़ना पड़ा।

+0

से लिया यह कैसे always_inline विशेषता से अलग है? विकल्प के साथ इस ध्वज का उपयोग करते समय इनलाइन की गारंटी है? या यह सिर्फ एक संकेत है? – DavidS

+0

चुनने का आदेश एलएलवीएम आईआर पर हमेशा इनलाइन रूपांतरण पास चलाने के लिए कहता है। यह पास आईआर के माध्यम से जाता है और हमेशा के साथ सभी कार्यों को पाता है और इनलाइन करता है। स्रोत कोड को देख रहे हैं - http: // llvm।संगठन/दस्तावेज़/डॉक्सिजन/एचटीएमएल/इनलाइनअलेवे_8cpp_source.html, टिप्पणियां इंगित करती हैं कि इसे हमेशा की गई चीज़ों को रेखांकित करना चाहिए जो हमेशा_इनलाइन चिह्नित है और ऐसा करना संभव है। आप एक ऐसा पास लिख सकते हैं जो असफल हो जाए अगर उसे "always_inline" चिह्नित किसी फ़ंक्शन पर कोई कॉल मिलती है। – Brian

-3

ब्रूट फोर्स विधि बस इसे मैक्रो में बदल रहा है।

0

बस कुछ ही टिप्पणियां जो उपयोगी भी हो सकती हैं।

ओपी की टिप्पणी के लिए:

  1. एकाधिक static inline परिभाषाएँ एक चेतावनी है, क्योंकि यह उनमें से एक, कई अलग कार्यों कि सिर scratching के बहुत सारे पैदा कर सकता है बदल रहा है पर, पैदा कर सकता है, विशेष रूप से किक को इनलाइन अगर में और वास्तविक कॉल कथन के विभिन्न अनुक्रमों में वाष्पित होते हैं।
  2. इस समान प्रभाव के रूप में 1.
  3. इनलाइन किए जाने वाले एक अनुकूलन है हो सकता है और आप अपने संकलक मैनुअल गौर कर सकते हैं जब यह में (जैसे gcc doc page) किक को देखने के लिए। आमतौर पर, यह पहले स्तर पर है। this उत्तर भी देखें।

एक उपयोगी चर्चा और सिफारिश here मिल सकती है। C99 के लिए सलाह अभिव्यक्त किया जाता है इस प्रकार है:

  1. एक हेडर फाइल में निम्नलिखित को परिभाषित करने और इसे शामिल जहाँ भी यह आवश्यक है:

    inline void foo() { /*...*/ }

  2. एक ही स्रोत फ़ाइल में उपयोग करते हुए यह घोषणा

    extern inline foo();

  3. : extern बाह्य प्रतीक उत्पन्न करने के लिए

एलएलवीएम आईआर विधि प्रस्तावित के लिए, यह काम करता है लेकिन फिर आप स्रोत भाषा डोमेन पारित कर चुके हैं और नियमों के एक अलग सेट (उपकरण पर अत्यधिक निर्भर) के अधीन हैं। एक संक्षिप्त संकेतक चर्चा here मिल सकती है। बजना -mllvm -inline-सीमा = n

अधिक से अधिक पैरामीटर एन, अधिक आक्रामक इनलाइन किए जाने वाले हो जाएगा:

+0

डाउनवॉटेड होने पर मैं कुछ रचनात्मक प्रतिक्रिया/पॉइंटर्स/आदि की सराहना करता हूं। – compor

0

आप के साथ प्रयोग के साथ शुरू कर सकते हैं। डिफ़ॉल्ट 225 है इसलिए इसे कुछ बड़ा सेट करें। बड़े कोड आकार और बहुत संकुचित इनलाइनिंग के साथ लंबे संकलन के समय की अपेक्षा करें। जब आप रिटर्न ह्रासमान के बिंदु मारा आप कोड की रूपरेखा और अक्सर कहा जाता है लेकिन uninlined कार्यों के लिए देखने का प्रयास करें और उन्हें और भी अधिक इनलाइन किए जाने वाले विशेषता ((always_inline)) के साथ अंकन की कोशिश कर सकते हैं।

आप कार्यों में चिह्नित किया है, तो "इनलाइन", आप भी -inlinehint-सीमा -inline-सीमा से अधिक के साथ प्रयोग करें और देखें इस कुछ भी बदल जाता है कि क्या कर सकते हैं।

इसके अलावा, क्या आप लिंक-टाइम अनुकूलन के साथ संकलित हैं? उनके बिना इनलाइनिंग व्यक्तिगत संकलन इकाइयों तक ही सीमित है।

** groups.google.com forum