<= <ට වඩා වේගවත්ද?


1582

if( a < 901 )වඩා වේගයෙන් if( a <= 900 ).

මෙම සරල උදාහරණයේ හරියටම නොවේ, නමුත් ලූප් සංකීර්ණ කේතයේ සුළු කාර්ය සාධන වෙනස්කම් ඇත. ජනනය කරන ලද යන්ත්‍ර කේත සමඟ එය සත්‍යයක් නම් මෙය කළ යුතු යැයි මම සිතමි.


155
එහි historical තිහාසික වැදගත්කම, පිළිතුරේ ගුණාත්මකභාවය සහ කාර්ය සාධනයේ අනෙක් ඉහළම ප්‍රශ්න විවෘතව පැවතීම යන කරුණු සැලකිල්ලට ගෙන මෙම ප්‍රශ්නය වසා දැමිය යුතු බවට කිසිදු හේතුවක් මා දකින්නේ නැත (විශේෂයෙන් ම මකා නොදමනු ලැබේ) . බොහෝ විට එය අගුළු දැමිය යුතුය. එසේම, ප්‍රශ්නයම වැරදි තොරතුරු / බොළඳ වුවද, එය පොතක පළ වී තිබීම යන්නෙන් අදහස් වන්නේ එහි මුල් වැරදි තොරතුරු “විශ්වාසදායක” ප්‍රභවයන්හි කොතැනක හෝ පවතින බවයි. එම නිසා මෙම ප්‍රශ්නය tive ලදායී වන අතර එය නිරවුල් කිරීමට උපකාරී වේ.
ජේසන් සී

32
ඔබ සඳහන් කරන්නේ කුමන පොතදැයි ඔබ කිසි විටෙකත් අපට පවසා නැත .
ජොනතන් රයින්හාර්ට්

162
ටයිප් <කිරීම ටයිප් කිරීමට වඩා දෙගුණයක් වේගවත් ය <=.
Deqing

8
එය සත්‍ය වූයේ 8086 දීය.
යෝෂුවා

7
උඩු යටිකුරු ගණන පැහැදිලිවම පෙන්නුම් කරන්නේ අධික ලෙස අධිතක්සේරු කරන මිනිසුන් සිය ගණනක් සිටින බවයි.
m93a

Answers:


1712

නැත, එය බොහෝ ගෘහ නිර්මාණ මත වේගවත් නොවනු ඇත. ඔබ නිශ්චිතව දක්වා නැත, නමුත් x86 හි, සියලු සමෝධානික සැසඳීම් සාමාන්‍යයෙන් යන්ත්‍ර උපදෙස් දෙකකින් ක්‍රියාත්මක වේ:

  • A testහෝ cmpඋපදෙස්, එය සකසයිEFLAGS
  • සහ Jcc(පැනීම) උපදෙස් , ඇති සැසැඳුම වර්ගය (සහ කේතය සැකැස්ම) මත පදනම්ව:
    • jne - සමාන නොවේ නම් පනින්න -> ZF = 0
    • jz - බිංදුව නම් පනින්න (සමාන) -> ZF = 1
    • jg - වැඩි නම් පනින්න -> ZF = 0 and SF = OF
    • (ආදිය ...)

උදාහරණය (සංක්ෂිප්තතාව සඳහා සංස්කරණය කරන ලදි) සමඟ සම්පාදනය කරන ලදි$ gcc -m32 -S -masm=intel test.c

    if (a < b) {
        // Do something 1
    }

සම්පාදනය කරන්නේ:

    mov     eax, DWORD PTR [esp+24]      ; a
    cmp     eax, DWORD PTR [esp+28]      ; b
    jge     .L2                          ; jump if a is >= b
    ; Do something 1
.L2:

සහ

    if (a <= b) {
        // Do something 2
    }

සම්පාදනය කරන්නේ:

    mov     eax, DWORD PTR [esp+24]      ; a
    cmp     eax, DWORD PTR [esp+28]      ; b
    jg      .L5                          ; jump if a is > b
    ; Do something 2
.L5:

එබැවින් මේ දෙක අතර ඇති එකම වෙනස උපදෙස් jgවලට එදිරිව ය jge. දෙදෙනා එකම කාලයක් ගතවනු ඇත.


විවිධ පැනීමේ උපදෙස් එකම කාලයක් ගත වන බව කිසිවක් ඇඟවුම් නොකරන අදහස් දැක්වීමට මම කැමතියි. මෙය පිළිතුරු දීමට ටිකක් උපක්‍රමශීලී ය, නමුත් මෙන්න මට දිය හැකි දේ: ඉන්ටෙල් උපදෙස් කට්ටල යොමුව තුළ , ඔවුන් සියල්ලන්ම එක පොදු උපදෙස් යටතේ කාණ්ඩ කර ඇත, Jcc(කොන්දේසිය සපුරා ඇත්නම් පනින්න). එම කන්ඩායමක් යටතේ එකට කර ඇත සුසර විමර්ශන අත්පොත උපග්රන්ථය සී වීම් හා කාර්ය දී.

කාලය අවම වීමයි - සම්බන්ධයෙන් උපදෙස් ඇති කරන μops සියලු ඝාතනය කර අවසන් කිරීමට ක්රියාත්මක හරය සඳහා අවශ්ය කරන බව ඔරලෝසුව පැදි ගණන.

ප්‍රතිදානය - නිකුත් කිරීමේ වරායට පෙර බලා සිටීමට අවශ්‍ය ඔරලෝසු චක්‍ර ගණන නැවත එකම උපදෙස් පිළිගැනීමට නිදහස ඇත. බොහෝ උපදෙස් සඳහා, උපදෙස් වල ප්‍රති put ලය එහි ප්‍රමාදයට වඩා සැලකිය යුතු ලෙස අඩු විය හැකිය

සඳහා වන අගයන් Jcc:

      Latency   Throughput
Jcc     N/A        0.5

පහත පාදසටහන සමඟ Jcc:

7) ශාඛා වල පුරෝකථන හැකියාව වැඩි දියුණු කිරීම සඳහා කොන්දේසි සහිත පැනීමේ උපදෙස් තෝරා ගැනීම පදනම් විය යුත්තේ 3.4.1 වගන්තියේ “ශාඛා පුරෝකථන ප්‍රශස්තකරණය” යන වගන්තිය මත ය. ශාඛා සාර්ථකව පුරෝකථනය කළ විට, ප්‍රමාදය jcceffectively ලදායී ලෙස ශුන්‍ය වේ.

එබැවින්, ඉන්ටෙල් ලේඛනයේ කිසිවක් කිසි විටෙකත් එක් Jccඋපදෙස් අනෙක් ඒවාට වඩා වෙනස් ලෙස සලකන්නේ නැත.

උපදෙස් ක්‍රියාත්මක කිරීම සඳහා භාවිතා කරන සත්‍ය පරිපථය ගැන යමෙකු සිතන්නේ නම් EFLAGS, කොන්දේසි සපුරා ඇත්දැයි තීරණය කිරීම සඳහා විවිධ බිටු වල සරල සහ / හෝ ගේට්ටු ඇති බව කෙනෙකුට උපකල්පනය කළ හැකිය . එවිට, බිටු දෙකක් පරීක්ෂා කරන උපදෙස් එක් පරීක්‍ෂණයකට වඩා වැඩි හෝ අඩු කාලයක් ගත වීමට කිසිදු හේතුවක් නැත (ගේට්ටු ප්‍රචාරණ ප්‍රමාදය නොසලකා හැරීම, එය ඔරලෝසු කාලයට වඩා බෙහෙවින් අඩුය.)


සංස්කරණය කරන්න: පාවෙන ස්ථානය

X87 පාවෙන ලක්ෂ්‍යය සඳහාද මෙය සත්‍ය වේ: (ඉහත කේතයට වඩා බොහෝ සෙයින් සමාන කේතය, නමුත් doubleඒ වෙනුවට int.)

        fld     QWORD PTR [esp+32]
        fld     QWORD PTR [esp+40]
        fucomip st, st(1)              ; Compare ST(0) and ST(1), and set CF, PF, ZF in EFLAGS
        fstp    st(0)
        seta    al                     ; Set al if above (CF=0 and ZF=0).
        test    al, al
        je      .L2
        ; Do something 1
.L2:

        fld     QWORD PTR [esp+32]
        fld     QWORD PTR [esp+40]
        fucomip st, st(1)              ; (same thing as above)
        fstp    st(0)
        setae   al                     ; Set al if above or equal (CF=0).
        test    al, al
        je      .L5
        ; Do something 2
.L5:
        leave
        ret

239
@Dyppl ඇත්තටම jgහා jnleඑම උපදෙස් වන අතර, 7F:-)
Jonathon Reinhart

17
එක් විකල්පයක් අනෙකට වඩා වේගවත් නම් ප්‍රශස්තිකරණයට කේතය වෙනස් කළ හැකි බව සඳහන් නොකල යුතුය.
එලසාර් ලීබෝවිච්

3
යම් දෙයක් එකම උපදෙස් ප්‍රමාණයක් ලබා දෙන නිසා, එම සියලු උපදෙස් ක්‍රියාත්මක කිරීමේ මුළු කාලය සමාන වේ යැයි අදහස් නොකෙරේ. ඇත්ත වශයෙන්ම තවත් උපදෙස් වේගයෙන් ක්‍රියාත්මක කළ හැකිය. එක් චක්‍රයකට උපදෙස් ස්ථාවර අංකයක් නොවේ, එය උපදෙස් අනුව වෙනස් වේ.
jontejj

22
ntjontejj මම ඒ ගැන ගොඩක් දන්නවා. ඔබ මගේ පිළිතුර පවා කියෙව්වාද ? එකම උපදෙස් ගණන ගැන මම කිසිවක් ප්‍රකාශ නොකළෙමි , එක් ප්‍රකාශයක් එක් ධජයක් දෙස බලන අතර අනෙක් පැනීමේ උපදෙස් කොඩි දෙකක් දෙස බලනවා හැර, ඒවා අනිවාර්යයෙන්ම එකම උපදෙස් වලට සම්පාදනය කර ඇති බව මම ප්‍රකාශ කළෙමි . ඒවා අර්ථාන්විතව සමාන බව පෙන්වීමට ප්‍රමාණවත් සාක්ෂි මා විසින් ලබා දී ඇති බව මම විශ්වාස කරමි.
ජොනතන් රයින්හාර්ට්

2
@jontejj ඔබ ඉතා හොඳ අදහසක් ඉදිරිපත් කරයි. මෙම පිළිතුර ලැබෙන තරමට දෘශ්‍යතාව සඳහා, මම එය පිරිසිදු කිරීමක් ලබා දිය යුතුය. ප්රතිචාර සඳහා ස්තූතියි.
ජොනතන් රයින්හාර්ට්

595

Ically තිහාසිකව (අපි කතා කරන්නේ 1980 සහ 1990 දශකයේ මුල් භාගයේ), මෙය සත්‍ය වූ සමහර ගෘහ නිර්මාණ ශිල්පය තිබුණි. මූල ගැටළුව වන්නේ පූර්ණ සංඛ්‍යා අඩු කිරීම හරහා පූර්ණ සංඛ්‍යා සංසන්දනය සහජයෙන්ම ක්‍රියාත්මක වීමයි. මෙය පහත දැක්වෙන අවස්ථා ඇති කරයි.

Comparison     Subtraction
----------     -----------
A < B      --> A - B < 0
A = B      --> A - B = 0
A > B      --> A - B > 0

දැන්, A < Bඅඩු කිරීම නිවැරදි වීමට ඉහළ බිට් එකක් ණයට ගැනීමට සිදු වූ විට, ඔබ අතින් එකතු කර අඩු කරන විට ඔබ ගෙන යන හා ණයට ගත් ආකාරයටම. මෙම "ණයට ගත්" බිට් සාමාන්‍යයෙන් රැගෙන යන බිට් ලෙස හැඳින්වෙන අතර එය ශාඛා උපදෙස් මගින් පරීක්ෂා කළ හැකිය. අඩු කිරීම සමානව සමාන වන ශුන්‍ය නම් ශුන්‍ය බිට් ලෙස හැඳින්වෙන දෙවන බිට් එකක් සැකසෙනු ඇත.

සාමාන්‍යයෙන් අවම වශයෙන් කොන්දේසි සහිත ශාඛා උපදෙස් දෙකක්වත් තිබුනි, එකක් රැගෙන යාමේ බිට් එකේ අතු බෙදීමට හා එකක් බිංදුවට.

දැන්, කාරණයේ හදවත ලබා ගැනීම සඳහා, රැගෙන යාම සහ බිට් බිට් ප්‍රති .ල ඇතුළත් කිරීම සඳහා පෙර වගුව පුළුල් කරමු.

Comparison     Subtraction  Carry Bit  Zero Bit
----------     -----------  ---------  --------
A < B      --> A - B < 0    0          0
A = B      --> A - B = 0    1          1
A > B      --> A - B > 0    1          0

එබැවින්, ශාඛාවක් ක්‍රියාත්මක කිරීම A < Bඑක් උපදෙස් වලින් කළ හැකිය, මන්ද රැගෙන යාමේ බිට් පැහැදිලි වන්නේ මේ අවස්ථාවේ දී පමණි, එනම්,

;; Implementation of "if (A < B) goto address;"
cmp  A, B          ;; compare A to B
bcz  address       ;; Branch if Carry is Zero to the new address

එහෙත්, අපට වඩා අඩු හෝ සමාන සංසන්දනයක් කිරීමට අවශ්‍ය නම්, සමානාත්මතාවය පිළිබඳ සිද්ධිය අල්ලා ගැනීම සඳහා ශුන්‍ය ධජයේ අතිරේක පරීක්‍ෂණයක් කළ යුතුය.

;; Implementation of "if (A <= B) goto address;"
cmp A, B           ;; compare A to B
bcz address        ;; branch if A < B
bzs address        ;; also, Branch if the Zero bit is Set

ඒ නිසා, සමහර පරිගණක මත, සන්සන්දනාත්මකව "වඩා අඩු" භාවිතා ශක්තිය ඉතිරි එක් යන්ත්රයක උපදෙස් . මෙය උප-මෙගාහර්ට්ස් ප්‍රොසෙසර වේගය සහ 1: 1 සීපීයූ සිට මතක වේගය දක්වා වූ යුගයේදී අදාළ වූ නමුත් අද එය මුළුමනින්ම පාහේ අදාල නොවේ.


10
මීට අමතරව, x86 වැනි ගෘහ නිර්මාණ ශිල්පය jgeමඟින් ශුන්‍යය පරීක්ෂා කරන සහ සලකුණු / රැගෙන යන කොඩි වැනි උපදෙස් ක්‍රියාත්මක කරයි.
ග්‍රේෆේඩ්

3
දී ඇති ගෘහ නිර්මාණ ශිල්පය සඳහා එය සත්‍යයක් වුවද. සම්පාදක ලේඛකයින් කිසිවෙකු මෙතෙක් දැක නැති, මන්දගාමී වේගය වේගයෙන් ආදේශ කිරීම සඳහා ප්‍රශස්තිකරණයක් එක් කළේ කුමක් ද?
ජෝන් හැනා

8
මෙය 8080 දී සත්‍ය වේ. එයට ශුන්‍යයට පැන us ණ මතට පනින්නට උපදෙස් ඇත, නමුත් එකවර දෙකම පරීක්ෂා කළ හැකි කිසිවක් නැත.

4
6502 සහ 65816 ප්‍රොසෙසර පවුලෙහි තත්වය මෙය වන අතර එය මෝටරෝලා 68HC11 / 12 දක්වා විහිදේ.
ලූකස්

31
මෙම 8080 මත පවා <=ටෙස්ට් ක්රියාත්මක කිරීමට හැකිය එක් වූ operands හුවමාරු හා පරීක්ෂා සමග උපදෙස් not <(සමාන >=මෙම අපේක්ෂිත ඇත) <=ජින් operands සමග: cmp B,A; bcs addr. මෙම පරීක්ෂණය ඉන්ටෙල් විසින් මඟ හැරුණු හේතුව එයයි, ඔවුන් එය අතිරික්තයක් ලෙස සැලකූ අතර ඔබට එම අවස්ථාවේදී අතිරික්ත උපදෙස් ලබා ගත නොහැකි විය :-)
ගුන්තර් පීස්

92

අපි කතා කරන්නේ අභ්‍යන්තර නිඛිල වර්ග ගැන යැයි සිතමු, එකක් අනෙකට වඩා වේගවත් විය හැකි ක්‍රමයක් නොමැත. ඒවා පැහැදිලිවම අර්ථාන්විතව සමාන ය. ඔවුන් දෙදෙනාම සම්පාදකයාගෙන් ඉල්ලා සිටින්නේ හරියටම එකම දේ කරන්න කියාය. මෙයින් එකක් සඳහා බාල කේත ජනනය කරන්නේ බිහිසුණු බිඳුණු සම්පාදකයෙකු පමණි.

ඇතැම් වේදිකාවක් තිබුණේ නම් <වඩා වේගයෙන් විය <=සරල පූර්ණ සංඛ්යාමය වර්ග සඳහා, සම්පාදකවරයා යුතු සෑම විටම පරිවර්තනය <=කිරීමට <ෙඤෙය. කිසියම් සම්පාදකයෙකු නරක සම්පාදකයෙකු නොවනු ඇත (එම වේදිකාව සඳහා).


6
+1 මම එකඟයි. වත් <හෝ <=සම්පාදකවරයා ඔවුන් සිදුවේවි වන වේගය තීරණය කරන තුරු වේගය තියෙනවා. සම්පාදකයින් සාමාන්‍යයෙන් මළ කේත ප්‍රශස්තිකරණය, වලිග ඇමතුම් ප්‍රශස්තිකරණය, ලූප් එසවීම (සහ වරින් වර ඉවත් කිරීම), විවිධ ලූප ස්වයංක්‍රීයව සමාන්තරකරණය කිරීම යනාදිය ඔබ සලකන විට මෙය ඉතා සරල ප්‍රශස්තිකරණයකි ... නොමේරූ ප්‍රශස්තිකරණය ගැන කල්පනා කරන්නේ ඇයි? ? මූලාකෘති ධාවනය ලබා ගන්න, වඩාත්ම වැදගත් ප්‍රශස්තිකරණය පවතින්නේ කොතැනදැයි තීරණය කිරීමට එය පැතිකඩ කරන්න, වැදගත්කම අනුව එම ප්‍රශස්තිකරණ සිදු කරන්න සහ ප්‍රගතිය මැනීම සඳහා නැවත පැතිකඩක් කරන්න ...
ඔටිසම්

උදා: සිට පරිවර්තනය විට එක් නිරන්තර වටිනාකමක් නැති සංසන්දනය <යටතේ මන්දගාමී විය හැකි සමහර නවීන නඩු තවමත් පවතින =, (a < C)කිරීමට (a <= C-1)(සමහර නිරන්තර සඳහා C) හේතු Cවන උපදෙස් කැටිය දී ආවරණ තවත් අසීරු විය. නිදසුනක් ලෙස, උපදෙස් කට්ටලයකට -127 සිට 128 දක්වා අත්සන් කරන ලද නියතයන් සංසන්දනාත්මකව සංයුක්ත ස්වරූපයෙන් නිරූපණය කළ හැකි නමුත්, එම පරාසයෙන් පිටත නියතයන් දිගු, මන්දගාමී කේතීකරණයක් හෝ වෙනත් උපදෙස් භාවිතා කරමින් පැටවිය යුතුය. එබැවින් සංසන්දනය කිරීමකට (a < -127)සෘජු පරිවර්තනයක් නොතිබිය හැකිය.
BeeOnRope

EeBeeOnRope ගැටළුව වූයේ ඒවායේ විවිධ නියතයන් තිබීම නිසා වෙනස් වූ මෙහෙයුම් සිදු කිරීම කාර්ය සාධනය කෙරෙහි බලපෑම් කළ හැකිද යන්න නොව විවිධ නියතයන් භාවිතා කරමින් එකම ක්‍රියාකාරිත්වය ප්‍රකාශ කිරීම කාර්ය සාධනය කෙරෙහි බලපාන්නේද යන්නයි. අපි ඒ නිසා සංසන්දනය නැහැ කිරීමට ඔබ එහි කිසිදු තෝරා වී සිටින නිසා, ඔබට අවශ්ය එක භාවිත කරන්න. අපි සංසන්දනය කරන්නේ , එකම සත්‍ය වගුවක් ඇති බැවින් විවිධ කේතීකරණ හෝ වෙනස් උපදෙස් අවශ්‍ය නොවේ. එක් කේතන ක්‍රමයක් අනෙකාගේ කේතන ක්‍රමයට සමාන වේ. a > 127a > 128a > 127a >= 128
ඩේවිඩ් ෂ්වාට්ස්

මම ඔබේ ප්‍රකාශයට සාමාන්‍යයෙන් ප්‍රතිචාර දක්වමින් සිටියේ “[<= මන්දගාමී] වේදිකාවක් තිබුනේ නම් සම්පාදකයා සෑම විටම නියතයන් බවට පරිවර්තනය <=විය යුතුය <” යනුවෙනි. මා දන්නා පරිදි, එම පරිවර්තනයට නියතය වෙනස් කිරීම ඇතුළත් වේ. උදා, වේගවත් බැවින් a <= 42සම්පාදනය කෙරේ . සමහර අවස්ථා වලදී, එවැනි පරිවර්තනයක් ful ලදායී නොවනු ඇත, මන්ද නව නියතයට වැඩි හෝ මන්දගාමී උපදෙස් අවශ්‍ය විය හැකිය. ඇත්ත වශයෙන්ම හා සමාන වන අතර සම්පාදකයෙකු ආකෘති දෙකම (එකම) වේගවත්ම ආකාරයෙන් සංකේතනය කළ යුතුය, නමුත් එය මා කී දෙයට නොගැලපේ. a < 43<a > 127a >= 128
BeeOnRope

67

දෙකම වේගවත් නොවන බව මට පෙනේ. සම්පාදකයා එක් එක් කොන්දේසිය තුළ එකම යන්ත්‍ර කේතයක් වෙනස් අගයකින් ජනනය කරයි.

if(a < 901)
cmpl  $900, -4(%rbp)
jg .L2

if(a <=901)
cmpl  $901, -4(%rbp)
jg .L3

මගේ උදාහරණය if ලිනක්ස් හි x86_64 වේදිකාවේ GCC වෙතින් ය.

සම්පාදක ලේඛකයින් ඉතා බුද්ධිමත් පුද්ගලයන් වන අතර ඔවුන් මේ දේවල් ගැන සිතන අතර තවත් බොහෝ අය අප ගැන සැලකිලිමත් වේ.

එය නියතයක් නොවේ නම් එකම යන්ත්‍ර කේතය ජනනය වන බව මම දුටුවෙමි.

int b;
if(a < b)
cmpl  -4(%rbp), %eax
jge   .L2

if(a <=b)
cmpl  -4(%rbp), %eax
jg .L3

9
මෙය x86 සඳහා විශේෂිත බව සලකන්න.
මයිකල් පෙට්‍රෝටා

10
මම හිතන්නේ ඔබ එය භාවිතා කළ යුත්තේ if(a <=900)එය හරියටම සමාන සමයක් ජනනය කරන බව පෙන්වීමටයි :)
Lipis

2
DAdrianCornish කණගාටුයි .. මම එය සංස්කරණය කළෙමි .. එය අඩු හෝ වැඩි වශයෙන් සමාන වේ .. නමුත් ඔබ දෙවැන්න <= 900 ට වෙනස් කළහොත් asm කේතය හරියටම සමාන වනු ඇත :) එය දැන් බොහෝ දුරට සමාන ය .. නමුත් ඔබ දැනගන්න .. OCD සඳහා :)
ලිපිස්

3
@ බොන් එය (සත්‍ය) නම් දක්වා අඩු වී සම්පූර්ණයෙන්ම ඉවත් කළ හැකිය.
Qsario

5
මෙම ප්‍රශස්තිකරණය අදාළ වන්නේ නියත සැසඳීම් සඳහා පමණක් බව කිසිවෙකු පෙන්වා දී නැත . විචල්යයන් දෙකක් සංසන්දනය කිරීම සඳහා මෙය මේ ආකාරයෙන් සිදු නොවන බවට මට සහතික විය හැකිය.
ජොනතන් රයින්හාර්ට්

51

පාවෙන ලක්ෂ්‍ය කේතය සඳහා, <= සංසන්දනය නවීන ගෘහ නිර්මාණ ශිල්පයෙහි පවා සැබවින්ම මන්දගාමී විය හැකිය (එක් උපදෙස් අනුව). පළමු කාර්යය මෙන්න:

int compare_strict(double a, double b) { return a < b; }

PowerPC හි, පළමුව මෙය පාවෙන ලක්ෂ්‍ය සංසන්දනයක් සිදු කරයි (කුමන යාවත්කාලීන කිරීම් cr, කොන්දේසි ලේඛනය), පසුව කොන්දේසි ලේඛනය ජීපීආර් වෙත ගෙන යන අතර, “සංසන්දනය කළ ප්‍රමාණයට වඩා අඩුවෙන්” ස්ථානයට මාරු කර නැවත පැමිණේ. එය උපදෙස් හතරක් ගනී.

දැන් ඒ වෙනුවට මෙම ශ්‍රිතය සලකා බලන්න:

int compare_loose(double a, double b) { return a <= b; }

මේ සඳහා compare_strictඉහත සඳහන් කළ කාර්යයම අවශ්‍ය වේ , නමුත් දැන් උනන්දුවක් දක්වන බිටු දෙකක් තිබේ: "වඩා අඩු" සහ "සමාන විය." මේ සඳහා අමතර උපදෙස් අවශ්‍ය වේ (cror බිටු දෙක එකකට ඒකාබද්ධ - කොන්දේසි ලේඛනය බිට්වේස් හෝ) අවශ්‍ය වේ. එබැවින් compare_looseඋපදෙස් පහක් අවශ්‍ය වන අතර compare_strictහතරක් අවශ්‍ය වේ.

සම්පාදකයාට දෙවන ශ්‍රිතය එසේ ප්‍රශස්තිකරණය කළ හැකි යැයි ඔබ සිතනු ඇත:

int compare_loose(double a, double b) { return ! (a > b); }

කෙසේ වෙතත් මෙය NaNs වැරදි ලෙස හැසිරෙනු ඇත. NaN1 <= NaN2හා NaN1 > NaN2දෙකටම අවශ්ය සාවද්ය ඇගයීමට.


වාසනාවකට එය x86 (x87) හි මේ ආකාරයට ක්‍රියා නොකරයි. fucomipZF සහ CF සකසයි.
ජොනතන් රයින්හාර්ට්

4
@JonathonReinhart: මම හිතන්නේ ඔයා තමයි මේ PowerPC කරන දේ වැරදි වැටහීමක් - තත්ත්වය ලේඛනය cr වේ වගේ කොඩි කිරීමට සමාන ZFහා CFx86 සැකසුම මත. .
ඩියෙට්‍රික් එප්

IetDietrichEpp මගේ ප්‍රකාශයෙන් පසුව මා එකතු කිරීමට අදහස් කළේ: EFLAGS හි වටිනාකම මත පදනම්ව ඔබට වහාම පැනිය හැකිය. පැහැදිලි නොවීම ගැන කණගාටුයි.
ජොනතන් රයින්හාර්ට්

1
On ජොනතන් රයින්හාර්ට්: ඔව්, ඔබට CR හි වටිනාකම මත පදනම්ව වහාම පැනිය හැකිය. පිළිතුර පැනීම ගැන කතා කිරීම නොවේ, අමතර උපදෙස් ලැබෙන්නේ එතැනිනි.
ඩියෙට්‍රික් එප්

34

සමහර විට නම් නොකල එම පොතේ කතුවරයා කියවා ඇති අතර එය විශ්වීයව සත්‍ය යැයි a > 0සිතනවාට වඩා වේගයෙන් දිව a >= 1යයි.

නමුත් එයට 0සම්බන්ධ වන්නේ ( CMPගෘහ නිර්මාණ ශිල්පය මත පදනම්ව උදා. වෙනුවට ආදේශ කළ හැකි නිසා OR) මිස ඒ නිසා නොවේ <.


1
නිසැකවම, "නිදොස්කරණය" ගොඩනැගීමක දී, නමුත් (a >= 1)වඩා වේගයෙන් ධාවනය කිරීම සඳහා නරක සම්පාදකයෙකු අවශ්‍ය වනු ඇත (a > 0), මන්දයත් කලින් තිබූ දේ ප්‍රශස්තකරණයෙන් සුළු වශයෙන් පරිවර්තනය කළ හැකි බැවිනි ..
BeeOnRope

2
EeBeeOnRope ප්‍රශස්තිකරණයට ප්‍රශස්තිකරණය කළ හැකි සංකීර්ණ දේවල් මොනවාද සහ එය කිරීමට අසමත් වන පහසු දේවල් මොනවාද යන්න ගැන සමහර විට මම පුදුම වෙමි.
glglgl

1
ඇත්ත වශයෙන්ම, එය සැමවිටම වැදගත් වන්නේ ඉතා සුළු කාර්යයන් සඳහා asm ප්‍රතිදානය පරීක්ෂා කිරීමයි. ඉහත පරිවර්තනය ඉතා මූලික වන අතර දශක ගණනාවක් තිස්සේ සරල සම්පාදකයින් තුළ පවා එය සිදු කර ඇත.
BeeOnRope

32

අවම වශයෙන්, මෙය සත්‍ය නම් සම්පාදකයෙකුට <= b සිට! (අ> ආ) ඉතා සුළු වශයෙන් ප්‍රශස්තිකරණය කළ හැකි අතර, එබැවින් සැසඳීම සැබවින්ම මන්දගාමී වුවද, සියල්ලටම වඩා බොළඳ සම්පාදකයා සමඟ ඔබ වෙනසක් නොදකිනු ඇත. .


ඇයි! (අ> ආ) යනු <= b හි ප්‍රශස්තිකරණය කළ අනුවාදයකි. (අ> ආ) 2 ක් එකකින් ක්‍රියාත්මක නොවේද?
අභිෂේක් සිං

6
Bi අභිෂේක්සිං NOTසෑදී ඇත්තේ වෙනත් උපදෙස් වලින් ( jeඑදිරිව jne)
පවෙල් ගට්නර්

15

ඔවුන්ට එකම වේගයක් ඇත. සමහර විශේෂ ගෘහ නිර්මාණ ශිල්පය තුළ ඔහු / ඇය පැවසූ දේ හරි, නමුත් x86 පවුල තුළ අවම වශයෙන් මම දන්නවා ඔවුන් එක හා සමානයි. මන්ද මෙය සිදු කිරීම සඳහා CPU විසින් උපස්ථරයක් (a - b) සිදු කර ධජ ලේඛනයේ ධජ පරීක්ෂා කරනු ඇත. එම ලේඛනයේ බිටු දෙකක් ZF (ශුන්‍ය ධජය) සහ SF (සං flag ා ධජය) ලෙස හැඳින්වෙන අතර එය එක් චක්‍රයක් තුළ සිදු කරනු ලැබේ, මන්ද එය එක් ආවරණ මෙහෙයුමකින් එය කරනු ඇත.


14

මෙය සී සම්පාදනය කර ඇති යටින් පවතින ගෘහ නිර්මාණ ශිල්පය මත බෙහෙවින් රඳා පවතී. සමහර සකසනයන්ට සහ ගෘහ නිර්මාණ ශිල්පයට විවිධ චක්‍ර ගණනින් ක්‍රියාත්මක වන සමාන හෝ අඩු හෝ සමාන පැහැදිලි උපදෙස් තිබිය හැකිය.

සම්පාදකයාට එය වටා වැඩ කළ හැකි බැවින් එය අදාල නොවේ.


1
චක්‍රයේ වෙනසක් තිබේ නම්. 1) එය හඳුනාගත නොහැකි වනු ඇත. 2) එහි ලුණු වටිනා ඕනෑම සම්පාදකයෙකු දැනටමත් කේතයේ අර්ථය වෙනස් නොකර මන්දගාමී ස්වරූපයේ සිට වේගවත් ස්වරූපයට පරිවර්තනය කරයි. එබැවින් රෝපණය කරන ලද උපදෙස් සමාන වේ.
මාටින් යෝක්

සම්පුර්ණයෙන්ම එකඟ වූ විට, එය ඕනෑම අවස්ථාවක ඉතා සුළු හා මෝඩ වෙනසක් වනු ඇත. වේදිකා අ nost ෙයවාදියා විය යුතු පොතක සඳහන් කිරීමට කිසිවක් නැත.
ටෙල්ජින්

@lttlrck: මට තේරුණා. මට ටික වේලාවක් ගියා (මෝඩ මාව). ඒවායේ මිනුම් දරාගත නොහැකි වන පරිදි තවත් බොහෝ දේ සිදුවෙමින් පවතින නිසා ඒවා හඳුනාගත නොහැක. ප්‍රොසෙසර් කුටි / හැඹිලි මිස් / සං als ා / ක්‍රියාවලි මාරු කිරීම. සාමාන්‍ය මෙහෙයුම් තත්වයකදී තනි චක්‍රීය මට්ටමේ ඇති දේවල් භෞතිකව මැනිය නොහැක. ඔබේ මිනුම් වලින් ඔබට එම සියලු ඇඟිලි ගැසීම් ඉවත් කළ හැකි නම් (එය පුවරුවේ මතකය සහ මෙහෙයුම් පද්ධතියක් නොමැති චිපයක් මත ධාවනය කරන්න) එවිට ඔබට තවමත් කරදර වීමට ඔබේ ටයිමරයේ අචලතාව ඇත, නමුත් න්‍යායාත්මකව ඔබ එය දිගු කාලයක් ධාවනය කළහොත් ඔබට යමක් දැකිය හැකිය.
මාටින් යෝක්

12

ටීඑල්; ඩීආර් පිළිතුර

ගෘහ නිර්මාණ ශිල්පය, සම්පාදකයා සහ භාෂාව යන බොහෝ සංයෝජනයන් සඳහා එය ඉක්මන් නොවනු ඇත.

සම්පූර්ණ පිළිතුර

වෙනත් පිළිතුරු මත අතෙහි x86 නිර්මාණ ශිල්පය, මම දන්නේ නැහැ ARM (ඔබගේ උදාහරණයක් assembler බව පෙනේ වන) ගෘහ නිර්මාණ ශිල්පය ජනනය කරන ලද කේතය පිළිබඳව විශේෂයෙන් අදහස් කිරීමට තරම් ප්රමාණවත්, නමුත් මේක කදිම උදාහරණයක් වන්නේ ක්ෂුද්ර ප්රශස්තිකරණය කළ ඉතා ගෘහ නිර්මාණ ශිල්පය විශේෂිත වන අතර එය ප්‍රශස්තිකරණය වීමක් ලෙස ප්‍රති-ප්‍රශස්තිකරණයක් විය හැකිය .

එනිසා, මම යෝජනා කරන්නේ මේ ආකාරයේ ක්ෂුද්‍ර ප්‍රශස්තිකරණය හොඳම මෘදුකාංග ඉංජිනේරු භාවිතයට වඩා භාණ්ඩ ප්‍රවාහන වැඩසටහන් සඳහා උදාහරණයකි .

බොහෝ විට පවතී සමහර මෙය ප්රශස්තිකරණය කොහෙද නිර්මිතයන්, නමුත් විරුද්ධ සත්ය විය හැකි එහිදී මම අවම වශයෙන් එක් ගෘහ නිර්මාණ ශිල්පය පිළිබඳ දන්නවා. ගෞරවනීය ට්‍රාන්ස්පියුටර් ගෘහ නිර්මාණ ශිල්පයට තිබුණේ යන්ත්‍ර කේත උපදෙස් පමණක් සමාන හා වැඩි හෝ සමාන හෝ සමාන ය , එබැවින් සියලු සැසඳීම් මෙම ප්‍රාථමිකයන්ගෙන් සෑදිය යුතුව තිබුණි.

එසේ වුවද, සෑම අවස්ථාවකම පාහේ, සම්පාදකයාට ඇගයීමේ උපදෙස් ඇණවුම් කළ හැකි වන පරිදි ප්‍රායෝගිකව කිසිදු සංසන්දනයකට වෙනත් කිසිදු වාසියක් නොතිබුණි. නරකම අවස්ථාව නම්, ඔපෙරන්ඩ් තොගයේ ඉහළම අයිතම දෙක මාරු කිරීම සඳහා ප්‍රතිලෝම උපදෙස් (REV) එකතු කිරීම අවශ්‍ය විය හැකිය. . මෙය තනි බයිට් උපදෙස් වන අතර එය ක්‍රියාත්මක කිරීමට තනි චක්‍රයක් ගත විය.

නැද්ද යන්න මේ වගේ ක්ෂුද්ර ප්රශස්තිකරණය යනු ප්රශස්තිකරණය හෝ ප්රති-ප්රශස්තිකරණය එය, ගෘහ නිර්මාණ ශිල්පය විශේෂිත ක්ෂුද්ර optimisations භාවිතා කිරීමේ පුරුද්ද ලබා ගැනීමට සාමාන්යයෙන් නරක අදහසක් එසේ වෙනත් ආකාරයකින් ඔබට ඉවෙන් මෙන් සමහරවිට, ඔබ භාවිතා කරන විශේෂිත ගෘහ නිර්මාණ ශිල්පය මත රඳා පවතී එසේ කිරීමට නුසුදුසු විට එකක් භාවිතා කරන්න, එවිට ඔබ කියවන පොත අනුබල දෙන දේ මෙය බව පෙනේ.


6

යම් වෙනසක් තිබුණත් ඔබට වෙනස හඳුනාගත නොහැකි විය යුතුය. ඊට අමතරව, ප්‍රායෝගිකව, ඔබ මැජික් නියතයන් භාවිතා කිරීමට යන්නේ නැත්නම් ඔබට අතිරේක දෙයක් කිරීමට a + 1හෝ a - 1තත්වය ස්ථාවර කිරීමට සිදුවනු ඇත, එය සෑම ආකාරයකින්ම ඉතා නරක පුරුද්දකි.


1
නරක පුරුද්ද කුමක්ද? කවුන්ටරයක් ​​වැඩි කිරීම හෝ අඩු කිරීම? එසේනම් ඔබ දර්ශක අංකනය ගබඩා කරන්නේ කෙසේද?
jcolebrand

5
ඔහු අදහස් කරන්නේ ඔබ විචල්ය වර්ග 2 ක් සංසන්දනය කරන්නේ නම්. ඇත්ත වශයෙන්ම ඔබ ලූපයක් හෝ යමක් සඳහා අගය සකසන්නේ නම් එය ඉතා සුළු කාරණයකි. නමුත් ඔබට x <= y තිබේ නම් සහ y
නොදන්නේ

Ust ජස්ටින් ඩැනියෙල්සන් එකඟ විය. කැත, ව්‍යාකූල ආදිය ගැන සඳහන් නොකල යුතුය
ජොනතන් රයින්හාර්ට්

4

අමතර අක්ෂර වින්‍යාසය තරමක් මන්දගාමී කේත සැකසීමට හේතු වන බැවින් බොහෝ ස්ක්‍රිප්ටින් භාෂාවල රේඛාව නිවැරදි යැයි ඔබට පැවසිය හැකිය. කෙසේ වෙතත්, ඉහළ පිළිතුර පෙන්වා දුන් පරිදි, එය C ++ හි කිසිදු බලපෑමක් ඇති නොකළ යුතු අතර, ස්ක්‍රිප්ටින් භාෂාවක් සමඟ කරන ඕනෑම දෙයක් ප්‍රශස්තිකරණය ගැන එතරම් තැකීමක් නොකරයි.


මම තරමක් එකඟ නොවෙමි. තරඟකාරී වැඩසටහන්කරණයේදී, ස්ක්‍රිප්ටින් භාෂාවන් බොහෝ විට ගැටලුවකට ඉක්මන්ම විසඳුම ලබා දෙයි, නමුත් නිවැරදි විසඳුමක් ලබා ගැනීම සඳහා නිවැරදි ශිල්පීය ක්‍රම (කියවීම: ප්‍රශස්තිකරණය) යෙදිය යුතුය.
ටයිලර් ක්‍රොම්ප්ටන්

3

මම මෙම පිළිතුර ලියන විට, මම බැලුවේ <එදිරිව <= පොදුවේ මාතෘකාව පිළිබඳ ප්‍රශ්නය පමණි, නියත a < 901එදිරිව එදිරිව නිශ්චිත උදාහරණය නොවේ a <= 900. බොහෝ සම්පාදකයින් සෑම විටම <හා අතර පරිවර්තනය කිරීමෙන් නියතයන්ගේ විශාලත්වය හැකිලී යයි<= , උදා.

ARM සහ විශේෂයෙන් AArch64 සඳහා, ක්ෂණිකව කේතනය කිරීමට හැකිවීම රඳා පවතින්නේ වචනයක ඕනෑම ස්ථානයකට පටු ක්ෂේත්‍රයක් භ්‍රමණය කිරීමේ හැකියාව මත ය. එනිසා cmp w0, #0x00f000සංකේතවත් කළ හැකියcmp w0, #0x00effff නොවිය හැකි කළ හැකිය. එබැවින් සංසන්දනය කිරීම සඳහා වන කුඩා-රීතිය එදිරිව. සම්පාදක කාල නියතය සැමවිටම AArch64 සඳහා අදාළ නොවේ.


<එදිරිව <= පොදුවේ, ධාවන කාල විචල්‍ය තත්වයන් ඇතුළුව

බොහෝ යන්ත්‍රවල එකලස් කිරීමේ භාෂාවෙන්, සංසන්දනයක් සඳහා සංසන්දනයකට <=සමාන පිරිවැයක් ඇත< . මෙය ඔබ අතු බෙදී සිටියද, 0/1 නිඛිලයක් නිර්මාණය කිරීම සඳහා එය බූලියනීකරණය කරන්නේද, නැතහොත් ශාඛා රහිත තෝරාගත් මෙහෙයුමක් සඳහා (x86 CMOV වැනි) පුරෝකථනයක් ලෙස භාවිතා කරන්නේද යන්න මෙය අදාළ වේ. අනෙක් පිළිතුරු ආමන්ත්‍රණය කර ඇත්තේ ප්‍රශ්නයේ මෙම කොටස පමණි.

නමුත් මෙම ප්‍රශ්නය C ++ ක්‍රියාකරුවන් ගැන වේ, ප්‍රශස්තකරණයට ආදානය . සාමාන්යයෙන් ඔවුන් දෙදෙනාම සමානව කාර්යක්ෂම වේ; පොතේ උපදෙස් මුළුමනින්ම ව්‍යාජ එකක් ලෙස පෙනෙන්නේ සම්පාදකයින්ට සෑම විටම ඔවුන් විසින් ක්‍රියාත්මක කරන සංසන්දනය පරිවර්තනය කළ හැකි බැවිනි. නමුත් භාවිතා කිරීමේදී අවම වශයෙන් එක් ව්‍යතිරේකයක්වත් තිබේ<= සම්පාදකයාට ප්‍රශස්තිකරණය කළ නොහැකි දෙයක් අහම්බෙන් නිර්මාණය කළ හැකි ඇත.

, චක්රයක් කොන්දේසියක් ලෙස, අවස්ථා තියෙනවා <=වේ ගුණාත්මක වෙනස් <එය චක්රයක් අනන්ත නොවන බව ඔප්පු සිට සම්පාදකවරයා නතර කරන විට,. මෙය ස්වයංක්‍රීය දෛශිකකරණය අක්‍රීය කරමින් විශාල වෙනසක් කළ හැකිය.

අත්සන් නොකළ පිටාර ගැලීම (යූබී) මෙන් නොව, පාදක -2 එතීම ලෙස හොඳින් අර්ථ දක්වා ඇත. අත්සන් කරන ලද පිටාර ගැලීම් යූබී මත පදනම්ව ප්‍රශස්තිකරණය කරන සම්පාදකයින් සමඟ අත්සන් කළ ලූප කවුන්ටර සාමාන්‍යයෙන් මෙයින් ආරක්ෂිත වේ: ++i <= sizeසෑම විටම අවසානයේ අසත්‍ය බවට පත්වේ. ( නිර්වචනය නොකළ හැසිරීම ගැන සෑම සී ක්‍රමලේඛකයෙකු දැනගත යුතු දේ )

void foo(unsigned size) {
    unsigned upper_bound = size - 1;  // or any calculation that could produce UINT_MAX
    for(unsigned i=0 ; i <= upper_bound ; i++)
        ...

සම්පාදකයින්ට ප්‍රශස්තිකරණය කළ හැක්කේ නිර්වචනය නොකළ හැසිරීමට තුඩු දෙන ඒවා හැර, හැකි සියලුම ආදාන අගයන් සඳහා C ++ ප්‍රභවයේ (අර්ථ දක්වා ඇති සහ නීත්‍යානුකූලව නිරීක්ෂණය කළ හැකි) හැසිරීම ආරක්ෂා කරන ආකාරවලින් පමණි .

(සරල i <= sizeද ප්රශ්නයක් ඇති කරනු ඇත, නමුත් මම ඉහළ බැඳී ගණනය අහම්බෙන් ඔබ ගැන සැලකිලිමත් නැහැ නමුත් සම්පාදකවරයා සලකා යුතු ආදාන සඳහා අසීමිත පුඩුවක් හැකියාව හඳුන්වා පිළිබඳව වඩා තත්වික උදාහරණයක් බවයි. කල්පනා)

මෙම අවස්ථාවේ දී, size=0මඟ පෙන්වන upper_bound=UINT_MAXඅතර i <= UINT_MAXසෑම විටම සත්‍ය වේ. එබැවින් මෙම ලූපය අසීමිත වන අතර size=0, සම්පාදකයාට ගරු කළ යුතුව ඇත්තේ ඔබ ක්‍රමලේඛකයා ලෙස කිසි විටෙකත් ප්‍රමාණය = 0 පසු කිරීමට අදහස් නොකරන බවයි. ප්‍රමාණය = 0 කළ නොහැකි බව ඔප්පු කළ හැකි සම්පාදකයාට මෙම ශ්‍රිතය ඇමතුම්කරුවකුට යොමු කළ හැකි නම්, නියමයි, එය හැකි තරම් ප්‍රශස්තිකරණය කළ හැකිය i < size.

Asm like if(!size) skip the loop; do{...}while(--size);යනු for( i<size )ලූපයක් ප්‍රශස්තිකරණය කිරීම සඳහා සාමාන්‍යයෙන් කාර්යක්ෂම ක්‍රමයකි, ලූපය තුළ සත්‍ය වටිනාකම iඅවශ්‍ය නොවේ නම් ( ලූප සෑම විටම "කරන්න ... අතර" විලාසිතාවට (වලිගය පැනීම) සම්පාදනය කරන්නේ ඇයි? ).

නමුත් එය}} අතර අසීමිත විය නොහැක: ඇතුලත් කළහොත් size==0අපට 2 ^ n පුනරාවර්තන ලැබේ. ( C සඳහා අත්සන් නොකල පූර්ණ සංඛ්‍යා හරහා නැවත සැකසීම මඟින් ශුන්‍යය ඇතුළුව අත්සන් නොකල සියලු සංඛ්‍යා වලට වඩා ලූපයක් ප්‍රකාශ කිරීමට හැකි වේ, නමුත් එය රැගෙන යන ධජයක් නොමැතිව එය පහසු නොවේ.)

ලූප් කවුන්ටරය ආවරණය කිරීමේ හැකියාවක් ඇති හෙයින්, නවීන සම්පාදකයින් බොහෝ විට "අත්හරින්න" වන අතර ආක්‍රමණශීලී ලෙස ප්‍රශස්තිකරණය නොකරන්න.

උදාහරණය: 1 සිට n දක්වා පූර්ණ සංඛ්‍යා එකතුව

i <= nගෝස්ගේsum(1 .. n)n * (n+1) / 2 සූත්‍රය මත පදනම්ව සංවෘත ස්වරූපයක් සහිත ලූප ප්‍රශස්තිකරණය කරන අත්සන් නොකල පරාජයන් ක්ලැන්ග්ගේ මුග්ධ හඳුනාගැනීම භාවිතා කිරීම.

unsigned sum_1_to_n_finite(unsigned n) {
    unsigned total = 0;
    for (unsigned i = 0 ; i < n+1 ; ++i)
        total += i;
    return total;
}

ගොඩ්බෝල්ට් සම්පාදක ගවේෂකයේ x86-64 asm ක්ලැන්ග් 7.0 සහ gcc8.2

 # clang7.0 -O3 closed-form
    cmp     edi, -1       # n passed in EDI: x86-64 System V calling convention
    je      .LBB1_1       # if (n == UINT_MAX) return 0;  // C++ loop runs 0 times
          # else fall through into the closed-form calc
    mov     ecx, edi         # zero-extend n into RCX
    lea     eax, [rdi - 1]   # n-1
    imul    rax, rcx         # n * (n-1)             # 64-bit
    shr     rax              # n * (n-1) / 2
    add     eax, edi         # n + (stuff / 2) = n * (n+1) / 2   # truncated to 32-bit
    ret          # computed without possible overflow of the product before right shifting
.LBB1_1:
    xor     eax, eax
    ret

නමුත් බොළඳ අනුවාදය සඳහා, අපට ක්ලැන්ග් වෙතින් ගොළු ලූපයක් ලැබේ.

unsigned sum_1_to_n_naive(unsigned n) {
    unsigned total = 0;
    for (unsigned i = 0 ; i<=n ; ++i)
        total += i;
    return total;
}
# clang7.0 -O3
sum_1_to_n(unsigned int):
    xor     ecx, ecx           # i = 0
    xor     eax, eax           # retval = 0
.LBB0_1:                       # do {
    add     eax, ecx             # retval += i
    add     ecx, 1               # ++1
    cmp     ecx, edi
    jbe     .LBB0_1            # } while( i<n );
    ret

GCC සංවෘත ස්වරූපයක් දෙයාකාරයෙන්ම භාවිතා නොකරයි, එබැවින් ලූප් තත්ත්වය තේරීමෙන් එය සැබවින්ම හානියක් නොවේ ; එය එක්ස්එම්එම් ලේඛනයක iමූලද්‍රව්‍යයන්ට සමාන්තරව අගයන් 4 ක් ධාවනය කරමින් සිම්ඩ් නිඛිල එකතු කිරීම සමඟ ස්වයංක්‍රීයව දෛශික කරයි .

# "naive" inner loop
.L3:
    add     eax, 1       # do {
    paddd   xmm0, xmm1    # vect_total_4.6, vect_vec_iv_.5
    paddd   xmm1, xmm2    # vect_vec_iv_.5, tmp114
    cmp     edx, eax      # bnd.1, ivtmp.14     # bound and induction-variable tmp, I think.
    ja      .L3 #,       # }while( n > i )

 "finite" inner loop
  # before the loop:
  # xmm0 = 0 = totals
  # xmm1 = {0,1,2,3} = i
  # xmm2 = set1_epi32(4)
 .L13:                # do {
    add     eax, 1       # i++
    paddd   xmm0, xmm1    # total[0..3] += i[0..3]
    paddd   xmm1, xmm2    # i[0..3] += 4
    cmp     eax, edx
    jne     .L13      # }while( i != upper_limit );

     then horizontal sum xmm0
     and peeled cleanup for the last n%3 iterations, or something.

එය ඉතා කුඩා n, සහ / හෝ අනන්ත ලූප් නඩුව සඳහා භාවිතා කරන බව සිතන සරල පරිමාණ පුඩුවක් ද ඇත.

බීටීඩබ්ලිව්, මෙම ලූප දෙකම ලූප උඩින් උපදෙස් (සහ සැන්ඩිබ්‍රිජ්-ෆැමිලි සීපීයූ මත යූඕපී) නාස්ති කරයි. sub eax,1/ jnzවෙනුවට add eax,1/ cmp / jcc වඩා කාර්යක්ෂම වනු ඇත. 2 වෙනුවට 1 uop (උප / ජේසීසී හෝ සීඑම්පී / ජේසීසී සාර්ව විලයනයෙන් පසුව). ලූප දෙකටම පසුව ඇති කේතය කොන්දේසි විරහිතව EAX ලියයි, එබැවින් එය ලූප් කවුන්ටරයේ අවසාන අගය භාවිතා නොකරයි.


කදිම ආදර්ශයකි. EFLAGS භාවිතය හේතුවෙන් ඇණවුම ක්‍රියාත්මක නොකිරීමේ විභව බලපෑමක් ගැන ඔබගේ අනෙක් අදහස ගැන කුමක් කිව හැකිද? එය තනිකරම න්‍යායාත්මකද? නැතහොත් ඇත්ත වශයෙන්ම JBE JBE ට වඩා හොඳ නල මාර්ගයක් කරා ගමන් කරයිද?
rustyx

@rustyx: වෙනත් පිළිතුරක් යටතේ කොතැනක හෝ මා එය ප්‍රකාශ කළාද? සම්පාදකයින් අර්ධ-ධජ කුටි ඇති කරන කේත විමෝචනය කිරීමට යන්නේ නැත, නිසැකවම C <හෝ සඳහා නොවේ <=. නමුත් වග බලා ගන්න, test ecx,ecx/ bt eax, 3/ jbeZF කට්ටලයක් (ecx == 0) නම් පනින්න, හෝ CF කට්ටලයක් (EAX == 1 ටිකක් 3), ඒ සියල්ල නැති මෙසේ කියැවේ කොඩි නිසා බොහෝ ජනිතවන තාපය මත අර්ධ ධජය ප්රදර්ශන කුටිය ඇති නම් ඇත ඕනෑම කොඩි ලිවීමට අවසාන උපදෙස් වලින් එන්න. සැන්ඩිබ්‍රිජ්-පවුල මත, එය සැබවින්ම ඇණහිට නැත, ඒකාබද්ධ කිරීමේ යූඕපයක් ඇතුළත් කළ යුතුය. cmp/ testසියලු ධජ ලියන්න, නමුත් btZF නවීකරණය නොකෙරේ. felixcloutier.com/x86/bt
පීටර්

2

පරිගණක නිර්මාණය කළ පුද්ගලයින් බූලියන් තර්කනය සමඟ නරක නම් පමණි. ඒවා නොවිය යුතුය.

සෑම සංසන්දනයක්ම (>= <= > < ) එකම වේගයකින් කළ හැකිය.

සෑම සංසන්දනයක්ම, අඩු කිරීමක් (වෙනස) සහ එය ධනාත්මක / .ණාත්මක දැයි බැලීම පමණි.
(නම්msb සකසා , අංකය negative ණ වේ)

පරීක්ෂා කරන්නේ කෙසේද a >= b? ධනාත්මක a-b >= 0දැයි උප පරීක්ෂාව a-b.
පරීක්ෂා කරන්නේ කෙසේද a <= b? ධනාත්මක 0 <= b-aදැයි උප පරීක්ෂාව b-a.
පරීක්ෂා කරන්නේ කෙසේද a < b? Negative a-b < 0ණාත්මකද යන්න උප පරීක්ෂාව a-b.
පරීක්ෂා කරන්නේ කෙසේද a > b? 0 > b-aනම් උප පරීක්ෂාවb-aNegative .

සරලව කිවහොත්, ලබා දී ඇති දෘෂ්ටි කෝණයෙන් පරිගණකයට මෙය කළ හැකිය:

a >= b== msb(a-b)==0
a <= b== msb(b-a)==0
a > b== msb(b-a)==1
a < b==msb(a-b)==1

ඇත්ත වශයෙන්ම පරිගණකයට ඇත්ත වශයෙන්ම ==0හෝ ==1එසේ කිරීමට අවශ්‍ය නොවනු ඇත.
සඳහා ==0එය හුදෙක් talk තෝරාගැනුම ප්රතිලෝම කරන්න හැකි msbපරිපථය සිට.

කෙසේ වෙතත්, ඔවුන් නිසැකවම ලොල් a >= bලෙස ගණනය නොකරනු ඇතa>b || a==b

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.