LINUX.ORG.RU

бага в gcc или мистика?


0

0

Под O2 и O3 провека 64 битного long на < 0 не работает правильно. Может ктото проверить у себя на машине?

g++ -v

Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.1-4ubuntu8' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu8) 
cat long_check.cpp
#include <iostream>
#include <vector>
#include <cmath>
#include <sstream>
#include <map>
#include <algorithm>
#include <stdlib.h>
#include <sys/time.h>

int main(int argc, char** argv)
{
        long hash = 5381;
        for(size_t i = 0; i<20; i++)
        {
                hash = (hash * 33);
                std::cerr<<hash<<" < 0 == "<<(hash<0)<<" ~~ ";
                std::cerr<<"(double)"<<hash<<" < 0 == "<<((double)hash<0)<<"\n";
        }
        return 0;
}
g++ -O1 long_check.cpp && ./a.out
177573 < 0 == 0 ~~ (double)177573 < 0 == 0
5859909 < 0 == 0 ~~ (double)5859909 < 0 == 0
193376997 < 0 == 0 ~~ (double)193376997 < 0 == 0
6381440901 < 0 == 0 ~~ (double)6381440901 < 0 == 0
210587549733 < 0 == 0 ~~ (double)210587549733 < 0 == 0
6949389141189 < 0 == 0 ~~ (double)6949389141189 < 0 == 0
229329841659237 < 0 == 0 ~~ (double)229329841659237 < 0 == 0
7567884774754821 < 0 == 0 ~~ (double)7567884774754821 < 0 == 0
249740197566909093 < 0 == 0 ~~ (double)249740197566909093 < 0 == 0
8241426519708000069 < 0 == 0 ~~ (double)8241426519708000069 < 0 == 0
-4734085955279271963 < 0 == 1 ~~ (double)-4734085955279271963 < 0 == 1
-8650883934539561851 < 0 == 1 ~~ (double)-8650883934539561851 < 0 == 1
-8778008734162266843 < 0 == 1 ~~ (double)-8778008734162266843 < 0 == 1
5473616951998020037 < 0 == 0 ~~ (double)5473616951998020037 < 0 == 0
-3838081321160854939 < 0 == 1 ~~ (double)-3838081321160854939 < 0 == 1
2470524917658648325 < 0 == 0 ~~ (double)2470524917658648325 < 0 == 0
7740345987897188261 < 0 == 0 ~~ (double)7740345987897188261 < 0 == 0
-2822999431326510011 < 0 == 1 ~~ (double)-2822999431326510011 < 0 == 1
-925260865227072283 < 0 == 1 ~~ (double)-925260865227072283 < 0 == 1
6359879594925717893 < 0 == 0 ~~ (double)6359879594925717893 < 0 == 0
g++ -O2 long_check.cpp && ./a.out
177573 < 0 == 0 ~~ (double)177573 < 0 == 0
5859909 < 0 == 0 ~~ (double)5859909 < 0 == 0
193376997 < 0 == 0 ~~ (double)193376997 < 0 == 0
6381440901 < 0 == 0 ~~ (double)6381440901 < 0 == 0
210587549733 < 0 == 0 ~~ (double)210587549733 < 0 == 0
6949389141189 < 0 == 0 ~~ (double)6949389141189 < 0 == 0
229329841659237 < 0 == 0 ~~ (double)229329841659237 < 0 == 0
7567884774754821 < 0 == 0 ~~ (double)7567884774754821 < 0 == 0
249740197566909093 < 0 == 0 ~~ (double)249740197566909093 < 0 == 0
8241426519708000069 < 0 == 0 ~~ (double)8241426519708000069 < 0 == 0
-4734085955279271963 < 0 == 0 ~~ (double)-4734085955279271963 < 0 == 1
-8650883934539561851 < 0 == 0 ~~ (double)-8650883934539561851 < 0 == 1
-8778008734162266843 < 0 == 0 ~~ (double)-8778008734162266843 < 0 == 1
5473616951998020037 < 0 == 0 ~~ (double)5473616951998020037 < 0 == 0
-3838081321160854939 < 0 == 0 ~~ (double)-3838081321160854939 < 0 == 1
2470524917658648325 < 0 == 0 ~~ (double)2470524917658648325 < 0 == 0
7740345987897188261 < 0 == 0 ~~ (double)7740345987897188261 < 0 == 0
-2822999431326510011 < 0 == 0 ~~ (double)-2822999431326510011 < 0 == 1
-925260865227072283 < 0 == 0 ~~ (double)-925260865227072283 < 0 == 1
6359879594925717893 < 0 == 0 ~~ (double)6359879594925717893 < 0 == 0


ну или так

#include <stdio.h>

int main(int argc, char** argv)
{
	long hash = 5381;
	for(size_t i = 0; i<20; i++)
	{
		hash = (hash * 33);
		printf("%ld : %d\n", hash, (hash<0));
	}
	return 0;
}

O1:

.LC0:
        .string "%ld : %d\n"
.globl main
        .type   main, @function
main:
.LFB31:
        .cfi_startproc
        .cfi_personality 0x3,__gxx_personality_v0
        pushq   %rbp
        .cfi_def_cfa_offset 16
        pushq   %rbx
        .cfi_def_cfa_offset 24
        subq    $8, %rsp
        .cfi_def_cfa_offset 32
        movl    $0, %ebp
        .cfi_offset 3, -24
        .cfi_offset 6, -16
        movl    $5381, %ebx
.L2:
        movq    %rbx, %rax
        salq    $5, %rax
        leaq    (%rax,%rbx), %rbx
        movq    %rbx, %rcx
        shrq    $63, %rcx
        movq    %rbx, %rdx
        movl    $.LC0, %esi
        movl    $1, %edi
        movl    $0, %eax
        call    __printf_chk
        addq    $1, %rbp
        cmpq    $20, %rbp
        jne     .L2
        movl    $0, %eax
        addq    $8, %rsp
        popq    %rbx
        popq    %rbp
        ret
        .cfi_endpro

O2:

.LC0:
        .string "%ld : %d\n"
        .p2align 4,,15
.globl main
        .type   main, @function
main:
.LFB31:
        .cfi_startproc
        .cfi_personality 0x3,__gxx_personality_v0
        pushq   %rbp
        .cfi_def_cfa_offset 16
        xorl    %ebp, %ebp
        .cfi_offset 6, -16
        pushq   %rbx
        .cfi_def_cfa_offset 24
        movl    $5381, %ebx
        .cfi_offset 3, -24
        subq    $8, %rsp
        .cfi_def_cfa_offset 32
        .p2align 4,,10
        .p2align 3
.L2:
        movq    %rbx, %rax
        xorl    %ecx, %ecx
        movl    $.LC0, %esi
        salq    $5, %rax
        movl    $1, %edi
        addq    $1, %rbp
        leaq    (%rax,%rbx), %rbx
        xorl    %eax, %eax
        movq    %rbx, %rdx
        call    __printf_chk
        cmpq    $20, %rbp
        jne     .L2
        addq    $8, %rsp
        xorl    %eax, %eax
        popq    %rbx
        popq    %rbp
        ret
        .cfi_endproc

stpg
() автор топика
Ответ на: комментарий от dimon555

а этот ноль-то какого типа, он тоже 64 битный?

hash = (hash * 33LL);
printf("%ld : %d\n", hash, (hash<0LL));

Результат тоже.

stpg
() автор топика

-Wstrict-overflow

This option is only active when -fstrict-overflow is active. It warns about cases where the compiler optimizes based on the assumption that
signed overflow does not occur. Note that it does not warn about all cases where the code might overflow: it only warns about cases where the
compiler implements some optimization. Thus this warning depends on the optimization level

"GCC по умолчанию считает поведение при знаковом переполнении неопределенным, чтобы делать лучшие оптимизации"

http://www.mail-archive.com/gcc@gcc.gnu.org/msg22631.html

gavv
()
Ответ на: комментарий от gavv

> «GCC по умолчанию считает поведение при знаковом переполнении неопределенным, чтобы делать лучшие оптимизации»

Да, оно. Спасибо

stpg
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.