This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c/65493] New: bug with 64/32 division sign related to various factors (-O3)


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65493

            Bug ID: 65493
           Summary: bug with 64/32 division sign related to various
                    factors (-O3)
           Product: gcc
           Version: 4.9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ml-gnubugzilla at worldspot dot net

Hi

Problem with a 64bit/32bit signed division with -O3 and various factors.

I found this weirg bug when using -O3 on various gcc versions.

platform: redhat el6.5 x84_64
tested gcc versions:
4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) target x86: 32 and 64bit (-m32 and -m64)
4.9.0 self compiled, target x86 32 and 64bit
4.8.0 self compiled, target sparc


the code:

#####################
#include<stdint.h>
#include<stdio.h>


void __attribute__ ((noinline)) xLoop16(
    int64_t h
,     int64_t hInc
,    int32_t l
,    int32_t lInc
,    int nElem
){
    for(;nElem>0;nElem-=1) {
        {
            int32_t x=h/l;
            printf(">>%08llx/%08x = %08x \n",h,l,x);
            h+=hInc;
            l+=lInc;
        }
        {
            int32_t x=h/l;
            printf(">>%08llx/%08x = %08x \n",h,l,x);
            h+=hInc;
            l+=lInc;
        }
    }
}
int main(){
    xLoop16(
        0x4337d8c0000LL
    ,    0x233dcbc8LL
    ,    0x748974b0L
    ,    0x08235a18L
    ,    4
    );
}
############################

The good result:

$ gcc test.c -O1  && ./a.out
>>4337d8c0000/748974b0 = 0000093a 
>>433a0c9cbc8/7caccec8 = 000008a0 
>>433c4079790/84d028e0 = fffff745 
>>433e7456358/8cf382f8 = fffff6a6 
>>4340a832f20/9516dd10 = fffff5f0 
>>4342dc0fae8/9d3a3728 = fffff51b 
>>43450fec6b0/a55d9140 = fffff420 
>>434743c9278/ad80eb58 = fffff2f4 

The bad result: the division result is always positive, it has become an
unsigned division:
$ gcc test.c -O3  && ./a.out
>>4337d8c0000/748974b0 = 0000093a 
>>433a0c9cbc8/7caccec8 = 000008a0 
>>433c4079790/84d028e0 = 00000819 
>>433e7456358/8cf382f8 = 000007a2 
>>4340a832f20/9516dd10 = 00000737 
>>4342dc0fae8/9d3a3728 = 000006d8 
>>43450fec6b0/a55d9140 = 00000682 
>>434743c9278/ad80eb58 = 00000634 


What changes the result to the good one:
- removing the noinline attribute
- change the for loop:
  for(nElem=4;nElem>0;nElem-=1) {
 instead of
  for(;nElem>0;nElem-=1) {
- there are 2 identical blocks in the loop. removing one gives a good result!


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]