Bug 28209 - gcc code generator produces 32-bit subtraction operation for long long
Summary: gcc code generator produces 32-bit subtraction operation for long long
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: gcc
Version: 7.0
Hardware: i386
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: David Lawrence
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2001-02-18 06:03 UTC by Need Real Name
Modified: 2007-04-18 16:31 UTC (History)
0 users

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2001-02-20 15:50:31 UTC
Embargoed:


Attachments (Terms of Use)
Simplified test case which triggers gcc bug. (1.23 KB, text/plain)
2001-02-18 06:05 UTC, Need Real Name
no flags Details

Description Need Real Name 2001-02-18 06:03:40 UTC
From Bugzilla Helper:
User-Agent: Mozilla/4.76 [en] (X11; U; Linux 2.2.16-22 i686)


When compiling the attached program with "gcc -O0" or "gcc -O1" it works
fine.  When compiling with "gcc -O2" or "gcc -O3" it crashes, printing out
the string "=== TEST FAILED! ===".

The problem seems to be that the code generator performs a 32-bit
subtraction on the long long (64-bit) values, generating an incorrect
result.  This problem seems to be quite sensitive to the calling context,
the attached test case is simplified as much as I could.

I submitted this bug to the gcc development team, and they claimed it was
not broken in their latest development builds, and hence the problem should
be referred to RedHat.  (bug report # 1562,
http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=1562&database=gcc)

Reproducible: Always
Steps to Reproduce:
1.  Compile the attached program.  "gcc -O2 gcc_bug.cc"
2.  Run it.  "./a.out"
3.  Look for the error message "=== TEST FAILED! ==="
4.  Cry.
	

Actual Results:  colohan:improv~/cvs/Tools/viola_bug> gcc -O2 gcc_bug.cc
colohan:improv~/cvs/Tools/viola_bug> ./a.out
=== TEST FAILED! ===
threadTimer2.current_time() = 17868864573449973892
process2->nfetch = 1132270
threadTimer2.time_base = 333418
Abort
Exit 134
colohan:improv~/cvs/Tools/viola_bug>

Expected Results:  colohan:improv~/cvs/Tools/viola_bug> gcc -O1 gcc_bug.cc
colohan:improv~/cvs/Tools/viola_bug> ./a.out
TEST PASSED!
colohan:improv~/cvs/Tools/viola_bug>

The test program:

#include <stdio.h>
#include <stdlib.h>

typedef unsigned long long uint64_t;
typedef long long int64_t;

struct Process2 {
    uint64_t nfetch;
} *process2;

struct ThreadTimer2 {
    uint64_t time_base;

    uint64_t current_time() {
        return process2->nfetch - time_base;
    }
} threadTimer2;

class EventMonTiming2 {
public:
    static uint64_t time_of_become_speculative;

    static void violate(uint64_t store_time);
};


uint64_t EventMonTiming2::time_of_become_speculative = 0;

int
main(int argc, char **argv)
{
    process2 = new Process2;


    threadTimer2.time_base = 333418;
    process2->nfetch = 1132270;
    EventMonTiming2::time_of_become_speculative = 0;

    EventMonTiming2::violate(799016);

    printf("TEST PASSED!\n");

    return 0;
}

void EventMonTiming2::violate(uint64_t store_time)
{
    uint64_t work_so_far =
        threadTimer2.current_time() - time_of_become_speculative;
    
    if(store_time < threadTimer2.current_time()) {
        if((int64_t)work_so_far < 0) {
            printf("=== TEST FAILED! ===\n"
                   "threadTimer2.current_time() = %llu\n"
                   "process2->nfetch = %llu\n"
                   "threadTimer2.time_base = %llu\n",
                   threadTimer2.current_time(),
                   process2->nfetch,
                   threadTimer2.time_base);
            
            abort();
        }
    }
}

Comment 1 Need Real Name 2001-02-18 06:05:21 UTC
Created attachment 10360 [details]
Simplified test case which triggers gcc bug.

Comment 2 Jakub Jelinek 2001-02-19 09:00:29 UTC
I've been able to reproduce it and it seems like it has been fixed somewhen
between Dec 04 and Dec 06 in CVS gcc, I'll dig into this deeper today.
For some reason %edx (high part of the nfetch value) seems to be clobbered
by the address where to load time_base from.

Comment 3 Jakub Jelinek 2001-02-20 15:50:25 UTC
Actually, it was fixed by:
2000-12-02  Bernd Schmidt  <bernds.uk>

        * reload1.c (free_for_value_p): New function, frontend to
        reload_reg_free_for_value_p.  All callers of the latter now call
        this function with an additional mode argument.

which will appear in gcc-2.96-76 (have just verified it fixes it and is exactly
what's going on - reload_reg_free_for_value_p would be called only on the first
register of the DImode register pair (ie. %eax) while with the patch it is
on both registers of the pair (ie. %eax and %edx), so %edx cannot be used for
other purposes afterwards.


Note You need to log in before you can comment on or make changes to this bug.