私はこの質問を読んでいましたが、それは受け入れられた答えです。コメントを読みましたが、最適化が行われた理由がわかりませんでした。
次のコードを使用すると、アセンブリ コードで分岐が発生するのはなぜですか?
x >= start && x <= end
編集:
明確にするために、受け入れられた回答によって生成された最適化の理由を理解したいと思います。私が理解しているのは、コンパイラによって生成されたアセンブリ コードに存在する分岐です。生成されたコードに分岐がある理由を理解したい。
私はこの質問を読んでいましたが、それは受け入れられた答えです。コメントを読みましたが、最適化が行われた理由がわかりませんでした。
次のコードを使用すると、アセンブリ コードで分岐が発生するのはなぜですか?
x >= start && x <= end
編集:
明確にするために、受け入れられた回答によって生成された最適化の理由を理解したいと思います。私が理解しているのは、コンパイラによって生成されたアセンブリ コードに存在する分岐です。生成されたコードに分岐がある理由を理解したい。
リンクされた質問の表現は根本的に異なることに注意してください
x >= start && x++ <= end
ここでの 2 番目のサブ式には副作用があるため、根本的に異なります。説明します。
&&
は短絡演算子であることに注意してください。これは、 が にx >= start
評価される場合false
、マシンは の評価に分岐できることx <= end
を意味します。
より正確には、コンパイラが の命令を発行するときに、x >= start && x <= end
がfalse に評価されたときに分岐する命令を発行できます。x <= end
x >= start
ただし、上記のステートメントでcanという言葉を使用することを強調します。この理由は、x <= end
副作用がないため、コンパイラがそれを評価して分岐するかどうかは問題ではないためです。
ただし、2 番目の式に副作用がある場合、コンパイラはそれを分岐する必要があります。&&
は短絡演算子であるため、に何らかの副作用がa && b
ある場合は、 が に評価される場合に観察してはなりません。これは、C およびほとんど (すべてではないにしても C に似た言語) での短絡の要件です。b
a
false
だから、特に、あなたが見るとき、
define POINT_IN_RANGE_AND_INCREMENT(p, range)
(p <= range.end && p++ >= range.start)
p++ >= range.start
2 番目の式には副作用があることに注意してください。p
つまり、(事後)インクリメント1
. しかし、その副作用は、 が にp <= range.end
評価される場合にのみ観察できtrue
ます。したがって、コンパイラは、ifが false と評価された場合の評価で分岐する必要があります。p++ >= range.start
p <= range.end
これが分岐する理由は、マシンがその式を評価するために、if がp <= range.end
に評価されるという事実を使用するためfalse
です。その後、式全体が に評価されることを自動的に認識し、副作用があるため評価すべきではありませんfalse
。したがって、式の 2 番目の部分を評価するために分岐する必要があります。したがって、アセンブリでは:p++ >= range.start
Ltmp1301:
ldr r1, [sp, #172] @ 4-byte Reload
ldr r1, [r1]
cmp r0, r1
bls LBB44_32
mov r6, r0 @ if the result of the compare is false
b LBB44_33 @ branch over evaluating the second expression
@ to avoid the side effects of p++
LBB44_32:
ldr r1, [sp, #188] @ 4-byte Reload
adds r6, r0, #1
Ltmp1302:
ldr r1, [r1]
cmp r0, r1
bhs LBB44_36
洞察に満ちたコメントをくださったOli Charlesworthに深く感謝いたします。