निम्नलिखित सभी निर्देश समान कार्य करते हैं: %eax
शून्य पर सेट । कौन सा तरीका इष्टतम है (सबसे कम मशीन चक्र की आवश्यकता है)?
xorl %eax, %eax
mov $0, %eax
andl $0, %eax
निम्नलिखित सभी निर्देश समान कार्य करते हैं: %eax
शून्य पर सेट । कौन सा तरीका इष्टतम है (सबसे कम मशीन चक्र की आवश्यकता है)?
xorl %eax, %eax
mov $0, %eax
andl $0, %eax
जवाबों:
टी एल; डॉ सारांश : xor same, same
है सभी CPU के लिए सबसे अच्छा विकल्प । किसी अन्य विधि का इस पर कोई लाभ नहीं है, और इसका किसी अन्य पद्धति पर कम से कम कुछ लाभ है। यह इंटेल और एएमडी द्वारा आधिकारिक तौर पर अनुशंसित है, और कंपाइलर क्या करते हैं। 64-बिट मोड में, अभी भी उपयोग करते हैं xor r32, r32
, क्योंकि 32-बिट reg लिखने से ऊपरी 32 शून्य होता है । xor r64, r64
एक बाइट की बर्बादी है, क्योंकि इसे आरईएक्स उपसर्ग की आवश्यकता है।
इससे भी बदतर, सिल्वरमोंट केवल xor r32,r32
डिप-ब्रेकिंग के रूप में पहचानता है , न कि 64-बिट ऑपरेंड-आकार। इस प्रकार तब भी जब REX उपसर्ग अभी भी आवश्यक है क्योंकि आप r8..r15 का उपयोग कर रहे हैं xor r10d,r10d
, नहींxor r10,r10
।
जीपी-पूर्णांक उदाहरण:
xor eax, eax ; RAX = 0. Including AL=0 etc.
xor r10d, r10d ; R10 = 0
xor edx, edx ; RDX = 0
; small code-size alternative: cdq ; zero RDX if EAX is already zero
; SUB-OPTIMAL
xor rax,rax ; waste of a REX prefix, and extra slow on Silvermont
xor r10,r10 ; bad on Silvermont (not dep breaking), same as r10d everywhere else because a REX prefix is still needed for r10d or r10.
mov eax, 0 ; doesn't touch FLAGS, but not faster and takes more bytes
and eax, 0 ; false dependency. (Microbenchmark experiments might want this)
sub eax, eax ; same as xor on most but not all CPUs; bad on Silvermont for example.
xor al, al ; false dep on some CPUs, not a zeroing idiom. Use xor eax,eax
mov al, 0 ; only 2 bytes, and probably better than xor al,al *if* you need to leave the rest of EAX/RAX unmodified
एक वेक्टर रजिस्टर को शून्य करना आमतौर पर सबसे अच्छा होता है pxor xmm, xmm
। आम तौर पर यही होता है कि gcc क्या करता है (FP निर्देशों के साथ उपयोग करने से पहले)।
xorps xmm, xmm
समझ में आ सकता है। यह एक बाइट से छोटा है pxor
, लेकिन xorps
इंटेल pxor
नेहेलम पर निष्पादन पोर्ट 5 की आवश्यकता है, जबकि किसी भी पोर्ट (0/1/5) पर चल सकता है। (पूर्णांक और एफपी के बीच नेहेलम के 2 सी बायपास विलंब विलंबता आमतौर पर प्रासंगिक नहीं है, क्योंकि आउट-ऑफ-ऑर्डर निष्पादन आमतौर पर एक नई निर्भरता श्रृंखला की शुरुआत में छिपा सकता है)।
SnB- परिवार के माइक्रोआर्किटेक्चर्स पर, न तो ज़ोर-ज़ीरिंग के स्वाद को एक निष्पादन पोर्ट की भी आवश्यकता है। एएमडी पर, और प्री-नेहेल्म पी 6 / कोर 2 इंटेल, xorps
औरpxor
उसी तरह से संभाला जाता है (वेक्टर-पूर्णांक निर्देश के रूप में)।
128b वेक्टर इंस्ट्रक्शन के AVX वर्जन को रेज के ऊपरी भाग के रूप में अच्छी तरह से उपयोग करते हैं, इसलिए vpxor xmm, xmm, xmm
YMM (AVX1 / AVX2) या ZMM (AVX512), या किसी भी अन्य वेक्टर एक्सटेंशन को शून्य करने के लिए एक अच्छा विकल्प है। vpxor ymm, ymm, ymm
हालांकि, एनकोडिंग के लिए कोई अतिरिक्त बाइट नहीं लेता है, और इंटेल पर समान चलता है, लेकिन ज़ेन 2 (2 उफ़) से पहले एएमडी पर धीमा। AVX512 ZMM शून्यिंग के लिए अतिरिक्त बाइट्स (EVEX उपसर्ग के लिए) की आवश्यकता होगी, इसलिए XMM या YMM शून्यिंग को प्राथमिकता दी जानी चाहिए।
एक्सएमएम / वाईएमएम / जेडएमएम उदाहरण
# Good:
xorps xmm0, xmm0 ; smallest code size (for non-AVX)
pxor xmm0, xmm0 ; costs an extra byte, runs on any port on Nehalem.
xorps xmm15, xmm15 ; Needs a REX prefix but that's unavoidable if you need to use high registers without AVX. Code-size is the only penalty.
# Good with AVX:
vpxor xmm0, xmm0, xmm0 ; zeros X/Y/ZMM0
vpxor xmm15, xmm0, xmm0 ; zeros X/Y/ZMM15, still only 2-byte VEX prefix
#sub-optimal AVX
vpxor xmm15, xmm15, xmm15 ; 3-byte VEX prefix because of high source reg
vpxor ymm0, ymm0, ymm0 ; decodes to 2 uops on AMD before Zen2
# Good with AVX512
vpxor xmm15, xmm0, xmm0 ; zero ZMM15 using an AVX1-encoded instruction (2-byte VEX prefix).
vpxord xmm30, xmm30, xmm30 ; EVEX is unavoidable when zeroing zmm16..31, but still prefer XMM or YMM for fewer uops on probable future AMD. May be worth using only high regs to avoid needing vzeroupper in short functions.
# Good with AVX512 *without* AVX512VL (e.g. KNL / Xeon Phi)
vpxord zmm30, zmm30, zmm30 ; Without AVX512VL you have to use a 512-bit instruction.
# sub-optimal with AVX512 (even without AVX512VL)
vpxord zmm0, zmm0, zmm0 ; EVEX prefix (4 bytes), and a 512-bit uop. Use AVX1 vpxor xmm0, xmm0, xmm0 even on KNL to save code size.
देखें vxorps-AMD पर जगमग / बुलडोजर / ज़ेन पर xmm रजिस्टर xmm रजिस्टर के साथ ymm की तुलना में तेज़ है? तथा
शूरवीरों के एकल या कुछ ZMM रजिस्टरों को खाली करने का सबसे कुशल तरीका क्या है?
अर्ध-संबंधित: सभी वन बिट्स में __m256 मान सेट करने के लिए सबसे तेज़ तरीका और
सीपीयू रजिस्टर में सभी बिट्स को 1 कुशलता से सेट करने के लिए AVX512 k0..7
मास्क रजिस्टर भी शामिल हैं । SSE / AVX vpcmpeqd
कई पर डेप-ब्रेकिंग कर रहा है (हालाँकि अभी भी 1s लिखने के लिए यूओपी की आवश्यकता है), लेकिन vpternlogd
ZMM रेज के लिए AVX512 भी डी-ब्रेकिंग नहीं है। एक लूप के अंदर एक ALU यूओपी के साथ फिर से बनाने के बजाय दूसरे रजिस्टर से कॉपी करने पर विचार करें, विशेष रूप से AVX512 के साथ।
लेकिन ज़ीरिंग सस्ता है: एक लूप के अंदर एक्सएमआर ज़ीरिंग को आमतौर पर कॉपी करना उतना ही अच्छा है, सिवाय कुछ एएमडी सीपीयू (बुलडोजर और ज़ेन) को छोड़कर, जिनके पास वेक्टर रेज के लिए वाई-एलिमिनेशन है, लेकिन फिर भी एक्सोर के लिए ज़ीरो लिखने के लिए एएलओ यूओपी चाहिए -zeroing।
कुछ सीपीयू sub same,same
एक शून्यिंग मुहावरे के रूप में पहचानते हैं xor
, लेकिन किसी भी शून्य मुहावरों को पहचानने वाले सभी सीपीयू पहचानते हैंxor
। बस xor
इसलिए आपको चिंता करने की ज़रूरत नहीं है कि कौन सा सीपीयू पहचानता है कि कौन सा शून्य मुहावरा है।
xor
(एक मान्यता प्राप्त शून्य मुहावरे के विपरीत, mov reg, 0
) कुछ स्पष्ट और कुछ सूक्ष्म फायदे हैं (सारांश सूची, फिर मैं उन पर विस्तार करूंगा):
mov reg,0
। (सभी सीपीयू)छोटे मशीन-कोड आकार (5 के बजाय 2 बाइट्स) हमेशा एक फायदा होता है: उच्चतर कोड घनत्व कम अनुदेश-कैश मिसेज़, और बेहतर अनुदेश लाने के लिए और संभावित रूप से डीकोड बैंडविड्थ की ओर जाता है।
इंटेल एसएनबी-परिवार माइक्रोआर्किटेक्चर पर एक्सोर के लिए एक निष्पादन इकाई का उपयोग नहीं करने का लाभ मामूली है, लेकिन बिजली बचाता है। यह SnB या IvB पर बात करने की अधिक संभावना है, जिसमें केवल 3 ALU निष्पादन पोर्ट हैं। हैसवेल और बाद में 4 निष्पादन पोर्ट हैं जो पूर्णांक ALU निर्देशों को संभाल सकते हैं, जिसमें शामिल हैंmov r32, imm32
शेड्यूलर द्वारा सही निर्णय लेने के साथ, (जो कि हमेशा अभ्यास में नहीं होता है), HSW अभी भी प्रति घड़ी 4 uops बनाए रख सकता है, जब भी उन्हें सभी ALU की आवश्यकता होती है निष्पादन बंदरगाहों।
देखें रजिस्टरों के शून्यीकरण के बारे में एक और सवाल पर मेरा उत्तर कुछ और जानकारी के लिए।
ब्रूस डॉसन का ब्लॉग पोस्ट जो माइकल पेटेक से जुड़ा हुआ है (प्रश्न पर टिप्पणी में) बताता है कि xor
एक निष्पादन इकाई (अप्रयुक्त डोमेन में शून्य उफ़) की आवश्यकता के बिना रजिस्टर-रीनेम चरण में संभाला जाता है, लेकिन इस तथ्य को याद किया कि अभी भी एक यूओपी है फ़्यूज़्ड डोमेन में। आधुनिक इंटेल सीपीयू प्रति घंटे 4 फ्यूजन-डोमेन यूपीएस जारी और रिटायर कर सकते हैं। यहीं से 4 जीरो प्रति घड़ी की सीमा आती है। हार्डवेयर का नाम बदलने के लिए रजिस्टर की बढ़ी हुई जटिलता केवल डिजाइन की चौड़ाई को सीमित करने के कारणों में से एक है। (ब्रूस ने एफपी गणित और x87 / SSE / राउंडिंग मुद्दों पर अपनी श्रृंखला जैसे कुछ बहुत ही उत्कृष्ट ब्लॉग पोस्ट लिखे हैं , जो मैं करता हूं। बहुत अधिक सिफारिश की जाती है)।
एएमडी बुलडोजर-परिवार CPUs पर , mov immediate
के रूप में ही EX0 / EX1 पूर्णांक निष्पादन बंदरगाहों पर रन xor
। mov reg,reg
AGU0 / 1 पर भी चल सकता है, लेकिन यह केवल रजिस्टर कॉपी के लिए है, न कि तुरंत सेट करने के लिए। तो AFAIK, एएमडी पर करने के लिए केवल लाभ xor
से अधिक mov
छोटे एन्कोडिंग है। यह भौतिक रजिस्टर संसाधनों को भी बचा सकता है, लेकिन मैंने कोई परीक्षण नहीं देखा है।
मान्यता प्राप्त शून्य मुहावरे इंटेल सीपीयू पर आंशिक-रजिस्टर दंड से बचते हैं जो पूर्ण रजिस्टरों (पी 6 और एसएनबी परिवारों) से अलग से आंशिक रजिस्टरों का नाम बदल देते हैं।
xor
होगा ऊपरी भागों ध्यान केंद्रित किया होने के रूप में रजिस्टर को टैग हां, xor eax, eax
/ inc al
/ inc eax
सामान्य आंशिक-रजिस्टर दंड है कि पूर्व IVB सीपीयू बचा जाता है। यहां तक कि बिना xor
, आईवीबी को केवल एक मर्जिंग यूओपी की आवश्यकता होती है जब उच्च 8 बिट्स ( AH
) को संशोधित किया जाता है और फिर पूरे रजिस्टर को पढ़ा जाता है, और हसवेल भी इसे हटा देता है।
एग्नर फॉग के माइक्रो गाइड, पृष्ठ 98 (पेंटियम एम सेक्शन, एसएनबी सहित बाद के वर्गों द्वारा संदर्भित) से:
प्रोसेसर एक रजिस्टर के XOR को शून्य पर सेट करने के साथ ही पहचानता है। रजिस्टर में एक विशेष टैग यह याद रखता है कि रजिस्टर का उच्च भाग शून्य है ताकि EAX = AL। यह टैग एक लूप में भी याद किया जाता है:
; Example 7.9. Partial register problem avoided in loop xor eax, eax mov ecx, 100 LL: mov al, [esi] mov [edi], eax ; No extra uop inc esi add edi, 4 dec ecx jnz LL
(pg82 से): प्रोसेसर को याद है कि EAX के ऊपरी 24 बिट्स तब तक शून्य होते हैं जब तक आपको कोई व्यवधान, गलतफहमी, या अन्य सीरियस इवेंट नहीं मिलता।
कि गाइड भी पुष्टि करता है कि की pg82 mov reg, 0
है नहीं जल्दी पी 6 पर एक के शून्यीकरण मुहावरा रूप में मान्यता प्राप्त, कम से कम PIII या PM तरह डिजाइन करती है। अगर वे बाद में सीपीयू पर इसका पता लगाने में ट्रांजिस्टर खर्च करते हैं तो मुझे बहुत आश्चर्य होगा।
xor
झंडे सेट करता है , जिसका अर्थ है कि आपको परिस्थितियों का परीक्षण करते समय सावधान रहना होगा। चूंकि setcc
दुर्भाग्य से केवल 8 बिट गंतव्य के साथ उपलब्ध है , इसलिए आपको आमतौर पर आंशिक-पंजीकृत दंड से बचने के लिए ध्यान रखना होगा।
यह अच्छा होता अगर x86-64 ने 16/32/64 बिट के लिए हटाए गए ऑपकोड (जैसे AAM) में से एक को पुन: उत्पन्न किया setcc r/m
, साथ ही साथ r / फ़ील्ड के स्रोत-रजिस्टर 3-बिट फ़ील्ड में एन्कोडेड predicate के साथ (रास्ता) कुछ अन्य एकल-ऑपरेंड निर्देश उन्हें ओपोड बिट्स के रूप में उपयोग करते हैं)। लेकिन उन्होंने ऐसा नहीं किया, और वैसे भी x86-32 के लिए मदद नहीं करेगा।
आदर्श रूप से, आपको xor
झंडे का उपयोग / सेट करना चाहिए setcc
/ पूरा रजिस्टर पढ़ना चाहिए :
...
call some_func
xor ecx,ecx ; zero *before* the test
test eax,eax
setnz cl ; cl = (some_func() != 0)
add ebx, ecx ; no partial-register penalty here
यह सभी सीपीयू (कोई स्टॉल, मर्जिंग उप्स, या गलत निर्भरता) पर इष्टतम प्रदर्शन करता है।
जब आप ध्वज-स्थापना निर्देश से पहले xor नहीं चाहते हैं तो चीजें अधिक जटिल होती हैं । उदाहरण के लिए, आप एक स्थिति पर शाखा लगाना चाहते हैं और फिर उसी झंडे से दूसरी शर्त पर सेट करें। उदाहरण के लिए cmp/jle
, sete
और आपके पास या तो एक अतिरिक्त रजिस्टर नहीं है, या आप xor
कोड नहीं किए गए कोड से बाहर रखना चाहते हैं।
कोई मान्यता प्राप्त शून्य मुहावरे नहीं हैं जो झंडे को प्रभावित नहीं करते हैं, इसलिए सबसे अच्छा विकल्प लक्ष्य माइक्रोआर्किटेक्चर पर निर्भर करता है। Core2 पर, एक मर्जिंग यूओपी डालने से 2 या 3 चक्र स्टाल हो सकता है। यह SnB पर सस्ता प्रतीत होता है, लेकिन मैंने इसे मापने की कोशिश में ज्यादा समय नहीं लगाया। पुराने इंटेल सीपीयू पर एक महत्वपूर्ण जुर्माना का उपयोग करना mov reg, 0
/ setcc
करना होगा, और अभी भी नए इंटेल पर कुछ हद तक खराब होगा।
इंटेल पी 6 और एसएनबी परिवारों के लिए उपयोग करना setcc
/ movzx r32, r8
करना शायद सबसे अच्छा विकल्प है, यदि आप ध्वज-सेटिंग निर्देश के आगे xor-शून्य नहीं कर सकते। यह एक xor-zeroing के बाद परीक्षण को दोहराने से बेहतर होना चाहिए। (यहां तक कि मानते हैं नहीं sahf
/ lahf
या pushf
/ popf
)। IvB को समाप्त कर सकते हैं movzx r32, r8
(यानी इसे बिना किसी निष्कासन इकाई या विलंबता के साथ रजिस्टर- रीनेमिंग के साथ संभाल सकते हैं , जैसे कि xor-zeroing)। Haswell और बाद में केवल नियमित रूप से खत्म करने mov
निर्देश है, तो movzx
एक निष्पादन इकाई लेता है और गैर शून्य विलंबता, परीक्षण बन गया है / setcc
/ movzx
बदतर xor
/ परीक्षण / setcc
, लेकिन अभी भी कम से कम अच्छा के रूप में के रूप में परीक्षा / mov r,0
/ setcc
(और ज्यादा बेहतर पुराने CPUs पर)।
एएमडी / पी 4 / सिल्वरमोंट पर पहले शून्य का उपयोग करना setcc
/ movzx
खराब होना, क्योंकि वे सब-रजिस्टरों के लिए अलग से ट्रैक नहीं करते हैं। रजिस्टर के पुराने मूल्य पर एक गलत चित्रण होगा। का उपयोग करते हुए mov reg, 0
/ setcc
के शून्यीकरण / निर्भरता तोड़ने के लिए शायद सबसे अच्छा विकल्प है जब है xor
/ परीक्षण / setcc
एक विकल्प नहीं है।
बेशक, यदि आपको setcc
8 बिट्स से अधिक व्यापक होने के लिए आउटपुट की आवश्यकता नहीं है, तो आपको कुछ भी शून्य करने की आवश्यकता नहीं है। हालाँकि, पी 6 / एसएनबी के अलावा सीपीयू पर गलत निर्भरता से सावधान रहें यदि आप एक रजिस्टर चुनते हैं जो हाल ही में एक लंबी निर्भरता श्रृंखला का हिस्सा था। (और यदि आप किसी फ़ंक्शन को कॉल करते हैं जो किसी फ़ंक्शन को सहेज रहा है / जो कि भाग का उपयोग कर रहा है तो उसे पुनर्स्थापित / पुनर्स्थापित कर सकता है)।
and
एक तत्काल शून्य के साथ किसी भी सीपीयू पर पुराने मूल्य के स्वतंत्र के रूप में विशेष-आवरण नहीं है, जिसके बारे में मुझे पता है, इसलिए यह निर्भरता श्रृंखला को नहीं तोड़ता है। इसके कोई फायदे नहीं हैं xor
और कई नुकसान हैं।
जब आप यह केवल microbenchmarks लिखने के लिए उपयोगी है चाहता हूँ एक विलंबता परीक्षण के हिस्से के रूप निर्भरता, लेकिन शून्यीकरण को और जोड़कर ज्ञात मान बनाना चाहते हैं।
सूक्ष्म विवरण के लिए http://agner.org/optimize/ देखें , जिसमें शून्यिंग मुहावरों को निर्भरता टूटने के रूप में मान्यता प्राप्त है (जैसे sub same,same
कुछ पर है, लेकिन सभी सीपीयू नहीं है, जबकि xor same,same
सभी पर मान्यता प्राप्त है।) mov
पुराने मूल्य पर निर्भरता श्रृंखला को तोड़ता है । रजिस्टर (स्रोत मूल्य की परवाह किए बिना, शून्य या नहीं, क्योंकि यही mov
काम करता है)। xor
केवल विशेष मामले में निर्भरता श्रृंखला को तोड़ता है जहां src और भाग्य एक ही रजिस्टर होते हैं, यही वजह mov
है कि विशेष रूप से मान्यता प्राप्त निर्भरता-तोड़ने वालों की सूची से बाहर रखा गया है । (इसके अलावा, क्योंकि इसे शून्य लाभ मुहावरे के रूप में मान्यता नहीं है, अन्य लाभों के साथ जो वहन करता है।)
दिलचस्प बात यह है कि, सबसे पुराना P6 डिज़ाइन ( पेंट्रो III के माध्यम से PPRO ) कोxor
-निर्भरता-ब्रेकर के रूप में पहचानना नहीं था , केवल आंशिक-रजिस्टर स्टालों से बचने के प्रयोजनों के लिए एक शून्य मुहावरे के रूप में, इसलिए कुछ मामलों में यह दोनों के लायक था mov
और फिर xor
-इस क्रम में डिपो को तोड़ने के लिए और फिर शून्य फिर से + आंतरिक टैग बिट सेट करें कि उच्च बिट शून्य हैं ताकि EAX = AX = AL।
एग्नर फॉग का उदाहरण देखें 6.17। उनके माइक्रोफ़ोन पीडीएफ में। वह कहते हैं कि यह पी 2, पी 3, और यहां तक कि (प्रारंभिक?) पीएम पर भी लागू होता है। लिंक्ड ब्लॉग पोस्ट पर एक टिप्पणी में कहा गया है कि यह केवल Ppro था, जिसकी यह निगरानी थी, लेकिन मैंने कटमई PIII पर परीक्षण किया है, और @Fanael ने एक पेंटियम एम पर परीक्षण किया, और हम दोनों ने पाया कि इसने एक विलंबता के लिए निर्भरता नहीं तोड़ी है -बाउंड imul
चेन। यह दुर्भाग्य से, एगनर फॉग के परिणामों की पुष्टि करता है।
यदि यह वास्तव में आपके कोड को अच्छा बनाता है या निर्देश बचाता है, तो सुनिश्चित करें mov
कि झंडे को छूने से बचने के लिए शून्य है , जब तक कि आप कोड आकार के अलावा किसी प्रदर्शन समस्या का परिचय नहीं देते हैं। क्लोबरिंग झंडे से बचना ही उपयोग न करने का एकमात्र समझदार कारण है xor
, लेकिन कभी-कभी आप उस चीज़ के आगे xor-शून्य कर सकते हैं जो फ़्लैग सेट करता है यदि आपके पास कोई अतिरिक्त रजिस्टर है।
mov
-एजरो आगे से setcc
विलंबता के लिए बेहतर है movzx reg32, reg8
(इंटेल पर छोड़कर जब आप विभिन्न रजिस्टर उठा सकते हैं), लेकिन बदतर कोड आकार।
mov reg, src
ओओ सीपीयू के लिए डिपो चेन को भी तोड़ता है (भले ही src के इम 332 [mem]
, या किसी अन्य रजिस्टर की परवाह किए बिना )। अनुकूलन-नियमावली में इस निर्भरता-विच्छेद का उल्लेख नहीं मिलता है क्योंकि यह कोई विशेष मामला नहीं है जो केवल तब होता है जब src और dest एक ही रजिस्टर हो। यह हमेशा उन निर्देशों के लिए होता है जो उनके भाग्य पर निर्भर नहीं करते हैं। ( popcnt/lzcnt/tzcnt
नियति पर झूठे डिपो होने के इंटेल के कार्यान्वयन को छोड़कर ।)
mov
मुक्त नहीं करता है , केवल शून्य विलंबता है। "निष्पादन पोर्ट नहीं लेना" भाग आमतौर पर महत्वपूर्ण नहीं है। फ्यूज्ड-डोमेन थ्रूपुट आसानी से अड़चन, जासूसी हो सकता है। मिश्रण में लोड या स्टोर के साथ।
xor r64, r64
बस एक बाइट बर्बाद मत करो। जैसा कि आप कहते हैं कि xor r32, r32
विशेष रूप से KNL के साथ सबसे अच्छा विकल्प है। यदि आप और अधिक पढ़ना चाहते हैं, तो इस माइक्रो-मैनुअल में धारा 15.7 "स्वतंत्रता के विशेष मामले" देखें।