РЕДАКТИРОВАТЬ: увидел список сборки OP для моего кода. Я сомневаюсь, что сейчас это даже общая ошибка VS2011. Это может быть просто частный случай ошибки кода OP. Я запускал код OP как есть с clang 3.2, gcc 4.6.2 и VS2010, и во всех случаях максимальные различия составляли ~ 1%.
Просто скомпилировал исходники с подходящими модификациями моего ne.c
файла и флагов /O2
и /GL
. Вот источник
int ne1(int n) {
return n != 0;
}
int ne2(int n) {
return n < 0 || n > 0;
}
int ne3(int n) {
return !(n == 0);
}
int main() { int p = ne1(rand()), q = ne2(rand()), r = ne3(rand());}
и соответствующая сборка:
; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01
TITLE D:\llvm_workspace\tests\ne.c
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB OLDNAMES
EXTRN @__security_check_cookie@4:PROC
EXTRN _rand:PROC
PUBLIC _ne3
; Function compile flags: /Ogtpy
; COMDAT _ne3
_TEXT SEGMENT
_n$ = 8 ; size = 4
_ne3 PROC ; COMDAT
; File d:\llvm_workspace\tests\ne.c
; Line 11
xor eax, eax
cmp DWORD PTR _n$[esp-4], eax
setne al
; Line 12
ret 0
_ne3 ENDP
_TEXT ENDS
PUBLIC _ne2
; Function compile flags: /Ogtpy
; COMDAT _ne2
_TEXT SEGMENT
_n$ = 8 ; size = 4
_ne2 PROC ; COMDAT
; Line 7
xor eax, eax
cmp eax, DWORD PTR _n$[esp-4]
sbb eax, eax
neg eax
; Line 8
ret 0
_ne2 ENDP
_TEXT ENDS
PUBLIC _ne1
; Function compile flags: /Ogtpy
; COMDAT _ne1
_TEXT SEGMENT
_n$ = 8 ; size = 4
_ne1 PROC ; COMDAT
; Line 3
xor eax, eax
cmp DWORD PTR _n$[esp-4], eax
setne al
; Line 4
ret 0
_ne1 ENDP
_TEXT ENDS
PUBLIC _main
; Function compile flags: /Ogtpy
; COMDAT _main
_TEXT SEGMENT
_main PROC ; COMDAT
; Line 14
call _rand
call _rand
call _rand
xor eax, eax
ret 0
_main ENDP
_TEXT ENDS
END
ne2()
, в котором использовались операторы <
, >
и ||
, явно дороже. ne1()
и ne3()
, в которых используются операторы ==
и !=
соответственно, являются более краткими и эквивалентными.
Visual Studio 2011 находится в стадии бета. Я бы счел это ошибкой. Мои тесты с двумя другими компиляторами, а именно gcc 4.6.2 и clang 3.2, с переключателем оптимизации O2
дали точно такую же сборку для всех трех тестов (которые у меня были) на моем Коробка Windows 7. Вот краткое изложение:
$ cat ne.c
#include <stdbool.h>
bool ne1(int n) {
return n != 0;
}
bool ne2(int n) {
return n < 0 || n > 0;
}
bool ne3(int n) {
return !(n != 0);
}
int main() {}
дает с помощью gcc:
_ne1:
LFB0:
.cfi_startproc
movl 4(%esp), %eax
testl %eax, %eax
setne %al
ret
.cfi_endproc
LFE0:
.p2align 2,,3
.globl _ne2
.def _ne2; .scl 2; .type 32; .endef
_ne2:
LFB1:
.cfi_startproc
movl 4(%esp), %edx
testl %edx, %edx
setne %al
ret
.cfi_endproc
LFE1:
.p2align 2,,3
.globl _ne3
.def _ne3; .scl 2; .type 32; .endef
_ne3:
LFB2:
.cfi_startproc
movl 4(%esp), %ecx
testl %ecx, %ecx
sete %al
ret
.cfi_endproc
LFE2:
.def ___main; .scl 2; .type 32; .endef
.section .text.startup,"x"
.p2align 2,,3
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB3:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
call ___main
xorl %eax, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE3:
и с лязгом:
.def _ne1;
.scl 2;
.type 32;
.endef
.text
.globl _ne1
.align 16, 0x90
_ne1:
cmpl $0, 4(%esp)
setne %al
movzbl %al, %eax
ret
.def _ne2;
.scl 2;
.type 32;
.endef
.globl _ne2
.align 16, 0x90
_ne2:
cmpl $0, 4(%esp)
setne %al
movzbl %al, %eax
ret
.def _ne3;
.scl 2;
.type 32;
.endef
.globl _ne3
.align 16, 0x90
_ne3:
cmpl $0, 4(%esp)
sete %al
movzbl %al, %eax
ret
.def _main;
.scl 2;
.type 32;
.endef
.globl _main
.align 16, 0x90
_main:
pushl %ebp
movl %esp, %ebp
calll ___main
xorl %eax, %eax
popl %ebp
ret
Я предлагаю зарегистрировать это как ошибку с помощью Microsoft Connect. em >
Примечание: я скомпилировал их как исходный код C, так как не думаю, что использование соответствующего компилятора C ++ внесет здесь какие-либо существенные изменения.
person
dirkgently
schedule
31.05.2012
xor
инструкции? Они не выглядят релевантными для теста, поэтому они должны быть частью окружающего кода. - person Mark Ransom   schedule 31.05.2012xor
: edeax
перед первым тестом и что это остается действительным для следующего ... - person Andreas Magnusson   schedule 31.05.2012!=
, используйте> || <
). Или, по крайней мере, введите виртуальный вызов, что является единственной реальной ситуацией, когда это может происходить как отдельная функция. - person Ben Voigt   schedule 31.05.2012