例えば
Compiler Explorerでコンパイルしてみると、以下のようになりました。
コード:
extern int mode, oldData, newData;
#define AUTO 123
void test1(void) {
if(mode == AUTO)
oldData = newData;
}
void test2(void) {
if(mode == AUTO && oldData != newData)
oldData = newData;
}
コード:
test1:
cmpl $123, mode(%rip)
je .L4
ret
.L4:
movl newData(%rip), %eax
movl %eax, oldData(%rip)
ret
test2:
cmpl $123, mode(%rip)
je .L7
.L5:
ret
.L7:
movl newData(%rip), %eax
cmpl %eax, oldData(%rip)
je .L5
movl %eax, oldData(%rip)
ret
このコンパイル結果では、mode == AUTO のチェックの通過後 (.L4、.L7)、
oldData != newData が無いバージョンではretまで3命令ですが、
あるバージョンではretまで4~5命令となりました。
また、どちらでも必ずnewDataおよびoldDataへのアクセスが発生します。
したがって、oldData != newData が無い方が効率が良さそうな気がします。
ただし、実際の実行速度は、分岐予測・命令の並行実行・キャッシュなどによって変わる可能性があり、
こっちの方が早いと断言することはできなそうです。
また、このコンパイル結果はあくまで例であり、
コンパイラ・最適化レベル・ターゲットなどによって変わる可能性があります。
「余計」な条件 && oldData != newData を書く分、コーディングの効率は落ちるかもしれないですね。
例えば[url=https://gcc.godbolt.org/z/K8TTc38E7]Compiler Explorerでコンパイル[/url]してみると、以下のようになりました。
[code]
extern int mode, oldData, newData;
#define AUTO 123
void test1(void) {
if(mode == AUTO)
oldData = newData;
}
void test2(void) {
if(mode == AUTO && oldData != newData)
oldData = newData;
}
[/code]
[code]
test1:
cmpl $123, mode(%rip)
je .L4
ret
.L4:
movl newData(%rip), %eax
movl %eax, oldData(%rip)
ret
test2:
cmpl $123, mode(%rip)
je .L7
.L5:
ret
.L7:
movl newData(%rip), %eax
cmpl %eax, oldData(%rip)
je .L5
movl %eax, oldData(%rip)
ret
[/code]
このコンパイル結果では、mode == AUTO のチェックの通過後 (.L4、.L7)、
oldData != newData が無いバージョンではretまで3命令ですが、
あるバージョンではretまで4~5命令となりました。
また、どちらでも必ずnewDataおよびoldDataへのアクセスが発生します。
したがって、oldData != newData が無い方が効率が良さそうな気がします。
ただし、実際の実行速度は、分岐予測・命令の並行実行・キャッシュなどによって変わる可能性があり、
こっちの方が早いと断言することはできなそうです。
また、このコンパイル結果はあくまで例であり、
コンパイラ・最適化レベル・ターゲットなどによって変わる可能性があります。
「余計」な条件 && oldData != newData を書く分、コーディングの効率は落ちるかもしれないですね。