आइए GCC 5.1 के स्रोत कोड की व्याख्या करें कि -O100
यह देखने के लिए क्या होता है क्योंकि यह मैन पेज पर स्पष्ट नहीं है।
हम यह निष्कर्ष निकालेंगे:
- ऊपर कुछ भी
-O3
करने के लिए INT_MAX
के रूप में ही है -O3
, लेकिन यह आसानी से, भविष्य में बदल सकता है तो यह पर भरोसा नहीं करते।
- यदि आप पूर्णांकों से बड़ा दर्ज करते हैं तो GCC 5.1 अपरिभाषित व्यवहार करता है
INT_MAX
।
- तर्क में केवल अंक हो सकते हैं, या यह इनायत से विफल होता है। विशेष रूप से, यह नकारात्मक पूर्णांकों को शामिल नहीं करता है
-O-1
उपप्रोग्राम पर ध्यान दें
सबसे पहले तो याद रखें कि जीसीसी के लिए सिर्फ एक सामने के अंत है cpp
, as
, cc1
, collect2
। एक त्वरित ./XXX --help
कहता है कि केवल collect2
और cc1
ले लो -O
, तो चलो उन पर ध्यान केंद्रित करें।
तथा:
gcc -v -O100 main.c |& grep 100
देता है:
COLLECT_GCC_OPTIONS='-O100' '-v' '-mtune=generic' '-march=x86-64'
/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1 [[noise]] hello_world.c -O100 -o /tmp/ccetECB5.
तो -O
दोनों के लिए भेजा गया था cc1
और collect2
।
ओ में आम
common.opt एक GCC विशिष्ट CLI विकल्प वर्णन प्रारूप है जिसे इंटर्नल डॉक्यूमेंटेशन में वर्णित किया गया है और C को opth-gen.awk और optc-gen.awk द्वारा अनुवादित किया गया है ।
इसमें निम्नलिखित दिलचस्प लाइनें शामिल हैं:
O
Common JoinedOrMissing Optimization
-O<number> Set optimization level to <number>
Os
Common Optimization
Optimize for space rather than speed
Ofast
Common Optimization
Optimize for speed disregarding exact standards compliance
Og
Common Optimization
Optimize for debugging experience rather than speed or size
जो सभी O
विकल्पों को निर्दिष्ट करते हैं। ध्यान दें कि -O<n>
दूसरे से एक अलग परिवार में कैसे है Os
, Ofast
औरOg
।
जब हम निर्माण करते हैं, तो options.h
इसमें एक फ़ाइल उत्पन्न होती है:
OPT_O = 139, /* -O */
OPT_Ofast = 140, /* -Ofast */
OPT_Og = 141, /* -Og */
OPT_Os = 142, /* -Os */
एक बोनस के रूप में, जबकि हम \bO\n
अंदर की ओर इशारा कर रहे हैं common.opt
हम लाइनों को नोटिस करते हैं:
-optimize
Common Alias(O)
जो हमें सिखाता है कि --optimize
(डबल डैश क्योंकि यह फ़ाइल -optimize
पर एक डैश के साथ शुरू होता है .opt
) एक अनजाने उपनाम है -O
जिसके लिए इसका उपयोग किया जा सकता है--optimize=3
!
जहां OPT_O का उपयोग किया जाता है
अब हम grep:
git grep -E '\bOPT_O\b'
जो हमें दो फाइलों की ओर इशारा करता है:
चलो पहले नीचे ट्रैक करते हैं opts.c
opts.c: default_options_optimization
सभी opts.c
उपयोग अंदर होते हैं:default_options_optimization
।
हम यह देखने के लिए पीछे हटते हैं कि इस फ़ंक्शन को कौन कॉल करता है, और हम देखते हैं कि एकमात्र कोड पथ है:
main.c:main
toplev.c:toplev::main
opts-global.c:decode_opts
opts.c:default_options_optimization
और main.c
का प्रवेश बिंदु हैcc1
। अच्छा!
इस समारोह का पहला भाग:
integral_argument
जो atoi
स्ट्रिंग पर कॉल करता हैOPT_O
इनपुट तर्क को पार्स लिए है
opts->x_optimize
जहां opts
एक है के अंदर मूल्य संग्रहीत करता है struct gcc_opts
।
संरचना gcc_opts
व्यर्थ में टटोलने के बाद, हम देखते हैं कि यह struct
भी उत्पन्न होता है options.h
:
struct gcc_options {
int x_optimize;
[...]
}
x_optimize
लाइनों से कहाँ आता है:
Variable
int optimize
वर्तमान में common.opt
, और वह options.c
:
struct gcc_options global_options;
इसलिए हम अनुमान लगाते हैं कि यह वही है जो संपूर्ण कॉन्फ़िगरेशन वैश्विक स्थिति में है, और int x_optimize
अनुकूलन मान है।
255 एक आंतरिक अधिकतम है
में opts.c:integral_argument
, atoi
इनपुट तर्क पर लागू किया जाता है, इसलिए INT_MAX
एक ऊपरी बाध्य है। और अगर आप कुछ भी बड़ा करते हैं, तो ऐसा लगता है कि जीसीसी सी अपरिभाषित व्यवहार करता है। आउच?
integral_argument
atoi
यदि कोई वर्ण कोई अंक नहीं है, तो भी तर्क को बारीकी से लपेटता है और अस्वीकार करता है। इसलिए नकारात्मक मूल्य अनुग्रहपूर्वक विफल होते हैं।
वापस opts.c:default_options_optimization
, हम लाइन देखते हैं:
if ((unsigned int) opts->x_optimize > 255)
opts->x_optimize = 255;
ताकि ऑप्टिमाइज़ेशन लेवल को छोटा कर दिया जाए 255
। पढ़ते समय opth-gen.awk
मैं भर आया था:
# All of the optimization switches gathered together so they can be saved and restored.
# This will allow attribute((cold)) to turn on space optimization.
और उत्पन्न पर options.h
:
struct GTY(()) cl_optimization
{
unsigned char x_optimize;
जो बताता है कि क्यों छंटनी: विकल्पों को भी अग्रेषित किया जाना चाहिए cl_optimization
, जो एक का उपयोग करता हैchar
अंतरिक्ष को बचाने के लिए है। तो 255 वास्तव में एक आंतरिक अधिकतम है।
opts.c: maybe_default_options
पर वापस opts.c:default_options_optimization
, हम maybe_default_options
जो दिलचस्प लगता है भर में आते हैं। हम इसे दर्ज करते हैं, और फिर maybe_default_option
जहां हम एक बड़े स्विच तक पहुंचते हैं:
switch (default_opt->levels)
{
[...]
case OPT_LEVELS_1_PLUS:
enabled = (level >= 1);
break;
[...]
case OPT_LEVELS_3_PLUS:
enabled = (level >= 3);
break;
कोई >= 4
जांच नहीं है , जो इंगित करता है कि 3
सबसे बड़ा संभव है।
फिर हम की परिभाषा के लिए खोज OPT_LEVELS_3_PLUS
में common-target.h
:
enum opt_levels
{
OPT_LEVELS_NONE, /* No levels (mark end of array). */
OPT_LEVELS_ALL, /* All levels (used by targets to disable options
enabled in target-independent code). */
OPT_LEVELS_0_ONLY, /* -O0 only. */
OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os and -Og. */
OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os or -Og. */
OPT_LEVELS_1_PLUS_NOT_DEBUG, /* -O1 and above, but not -Og. */
OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os. */
OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os or -Og. */
OPT_LEVELS_3_PLUS, /* -O3 and above. */
OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os. */
OPT_LEVELS_SIZE, /* -Os only. */
OPT_LEVELS_FAST /* -Ofast only. */
};
हा! यह एक मजबूत संकेतक है कि केवल 3 स्तर हैं।
opts.c: default_options_table
opt_levels
इतना दिलचस्प है, कि हम मचलते हैं OPT_LEVELS_3_PLUS
, और सामने आते हैं opts.c:default_options_table
:
static const struct default_options default_options_table[] = {
/* -O1 optimizations. */
{ OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 },
[...]
/* -O3 optimizations. */
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
[...]
}
इसलिए यह वह जगह है जहां -On
डॉक्स में उल्लिखित विशिष्ट अनुकूलन मानचित्रण एन्कोडेड है। अच्छा!
आश्वासन दें कि x_optimize के लिए और अधिक उपयोग नहीं हैं
का मुख्य उपयोग मैन पेज पर प्रलेखित x_optimize
अन्य विशिष्ट अनुकूलन विकल्पों को सेट करना था -fdefer_pop
। क्या कोई और है?
हम grep
, और कुछ और पाते हैं। संख्या छोटी है, और मैनुअल निरीक्षण पर हम देखते हैं कि हर उपयोग केवल एक ही पर होता है x_optimize >= 3
, इसलिए हमारा निष्कर्ष है।
LTO-wrapper.c
अब हम दूसरी घटना के लिए जाते हैं OPT_O
, जो अंदर थी lto-wrapper.c
।
एलटीओ का अर्थ है लिंक टाइम ऑप्टिमाइज़ेशन, जैसा कि नाम से पता चलता है कि एक -O
विकल्प की आवश्यकता है, और इसे collec2
(जो मूल रूप से एक लिंक है) से जोड़ा जाएगा ।
वास्तव में, पहली पंक्ति lto-wrapper.c
कहती है:
/* Wrapper to call lto. Used by collect2 and the linker plugin.
इस फ़ाइल में, OPT_O
आवृत्तियाँ केवल O
इसे आगे पास करने के लिए मान को सामान्य करती हैं, इसलिए हमें ठीक होना चाहिए।
man gcc
Cygwin (12000 अजीब लाइनों) पर आप के लिए खोज कर सकते हैं-O
और सब कुछ राज्य नीचे जवाब मिल, और फिर कुछ।