Bug 16836 - gcc in RC2 miscompiles ia64 toolchain
Summary: gcc in RC2 miscompiles ia64 toolchain
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: gcc   
(Show other bugs)
Version: 7.0
Hardware: i386
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact:
URL: http://gcc.gnu.org/ml/gcc-bugs/2000-0...
Whiteboard:
Keywords:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2000-08-23 23:28 UTC by Red Hat Bugzilla
Modified: 2008-05-01 15:37 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2000-10-03 16:51:06 UTC
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
We should exclude edx for DImode. (653 bytes, patch)
2000-08-31 15:54 UTC, Red Hat Bugzilla
no flags Details | Diff
A patch for find_reg () (1.73 KB, patch)
2000-09-01 00:24 UTC, Red Hat Bugzilla
no flags Details | Diff
An updated patch for find_reg (). (1.98 KB, patch)
2000-09-01 14:58 UTC, Red Hat Bugzilla
no flags Details | Diff

Description Red Hat Bugzilla 2000-08-23 23:28:02 UTC
gcc in RC2 miscompiles ia64 0814 toolchain under ia32 with -O2 -fPIC.
assign_file_positions_for_segments () in bfd/elf.c from ia64 0814
toolchain is miscompiled. Around line 2875:

          if (p->p_type == PT_LOAD)
            {
              bfd_signed_vma adjust; 

              if ((flags & SEC_LOAD) != 0)
                {
                  adjust = sec->lma - (p->p_paddr + p->p_memsz);
                  if (adjust < 0)
                    adjust = 0;
                }
              else if ((flags & SEC_ALLOC) != 0)
                {
                  /* The section VMA must equal the file position
                     modulo the page size.  FIXME: I'm not sure if 
                     this adjustment is really necessary.  We used to 
                     not have the SEC_LOAD case just above, and then
                     this was necessary, but now I'm not sure.  */
                  if ((abfd->flags & D_PAGED) != 0)
                    adjust = (sec->vma - voff) % bed->maxpagesize;
                  else
                    adjust = (sec->vma - voff) % align;
                }
              else
               adjust = 0;

              if (adjust != 0)
                {
                  if (i == 0)
                    {
                      (* _bfd_error_handler)
                        (_("Error: First section in segment (%s) starts at
0x%x"),
                         bfd_section_name (abfd, sec), sec->lma);
                      (* _bfd_error_handler)
                        (_("       whereas segment starts at 0x%x"),
                         p->p_paddr);

                      return false;
                    }

The line:

	adjust = sec->lma - (p->p_paddr + p->p_memsz);

should set adjust to 0 if sec->lma == (p->p_paddr + p->p_memsz). However,
with -O2 -fPIC, it is set to sec->lma. As the result, I got

lt-ld-new: Error: First section in segment (.interp) starts at 0x1c8
lt-ld-new:        whereas segment starts at 0x0

Compile with -O -fPIC or -O2 generates the corrent code. I couldn't
find the smaller testcase.

H.J.

Comment 1 Red Hat Bugzilla 2000-08-24 02:49:55 UTC
Please see testcase at

http://gcc.gnu.org/ml/gcc-bugs/2000-08/msg00526.html

H.J.

Comment 2 Red Hat Bugzilla 2000-08-24 23:33:39 UTC
Known bug: 32->64 bit cross compilers are broken in the
current gcc.

Comment 3 Red Hat Bugzilla 2000-08-24 23:39:27 UTC
Please see my testcase. It has very little to do with cross compiler.
It is long long what is broken with -O2 -fPIC.

H.J.

Comment 4 Red Hat Bugzilla 2000-08-25 04:48:06 UTC
H.J. is right, this is serious problem in reload. I have spent some time
on it yesterday, but haven't figured out where the bug is yet.
BTW: The testcase can be trimmed down a little bit and -fpic is only
interesting to it because it makes %ebx a fixed register, thus increasing
register pressure.

Comment 5 Red Hat Bugzilla 2000-08-25 16:45:43 UTC
I spent an hour to get that testcase. It has only 79 lines -).

Comment 6 Red Hat Bugzilla 2000-08-30 22:35:02 UTC
I don't think this is a reload problem. I tracked it down to
try_split (). Given an RTL

(insn 83 291 254 (parallel[ 
            (set (reg:DI 0 eax)
                (plus:DI (reg:DI 0 eax)
                    (mem/s:DI (plus:SI (reg:SI 2 ecx)
                            (const_int 20 [0x14])) 10)))
            (clobber (reg:CC 17 flags))
        ] ) 108 {adddi3} (nil)
    (nil))

to

(sequence[ 
        (insn 292 0 293 (parallel[ 
                    (set (reg:CC 17 flags)
                        (plus:CC (reg:SI 0 eax)
                            (mem/s:SI (plus:SI (reg:SI 2 ecx)
                                    (const_int 20 [0x14])) 10)))
                    (set (reg:SI 0 eax)
                        (plus:SI (reg:SI 0 eax)
                            (mem/s:SI (plus:SI (reg:SI 2 ecx)
                                    (const_int 20 [0x14])) 10)))
                ] ) -1 (nil)
            (nil))
        (insn 293 292 0 (parallel[ 
                    (set (reg:SI 1 edx)
                        (plus:SI (reg:SI 1 edx)
                            (plus:SI (mem/s:SI (plus:SI (reg:SI 2 ecx)
                                        (const_int 24 [0x18])) 10)
                                (ltu:SI (reg:CC 17 flags)
                                    (const_int 0 [0x0])))))
                    (clobber (reg:CC 17 flags))
                ] ) -1 (nil)
            (nil))
    ] )

The problem is edx is used in

(insn 294 257 295 (set (reg:SI 1 edx)
        (mem/s:SI (reg:SI 4 esi) 10)) -1 (nil)
    (nil))  

a few instructiions down. As the result, the second part of the sequence
gets deleted later since edx is dead.


H.J.


Comment 7 Red Hat Bugzilla 2000-08-31 02:48:46 UTC
You are right. It is a reload bug. I don't think reload knows

(reg/v:DI 1 edx) == (reg:DI 0 eax))

It turns

(insn 86 257 87 (parallel[ 
            (set (reg/v:DI 1 edx)
                (minus:DI (mem/s:DI (reg/v:SI 43) 10)
                    (reg:DI 0 eax)))
            (clobber (reg:CC 17 flags))
        ] ) 129 {subdi3} (insn_list 83 (nil))
    (expr_list:REG_UNUSED (reg:CC 17 flags)
        (expr_list:REG_DEAD (reg:DI 0 eax)
            (nil))))

into

(insn 257 85 260 (set (reg:SI 4 esi)
        (reg/v:SI 43)) -1 (nil)
    (nil))

(insn 260 257 86 (set (reg/v:DI 1 edx)
        (mem/s:DI (reg/v:SI 43) 10)) -1 (nil)
    (nil))

(insn 86 260 87 (parallel[ 
            (set (reg/v:DI 1 edx)
                (minus:DI (mem/s:DI (reg/v:SI 43) 10)
                    (reg:DI 0 eax)))
            (clobber (reg:CC 17 flags))
        ] ) 129 {subdi3} (insn_list 83 (nil))
    (expr_list:REG_UNUSED (reg:CC 17 flags)
        (expr_list:REG_DEAD (reg:DI 0 eax)
            (nil))))

From then on, everything goes downhill. I will take another look
tomorror.


Comment 8 Red Hat Bugzilla 2000-08-31 15:54:17 UTC
Created attachment 3122 [details]
We should exclude edx for DImode.

Comment 9 Red Hat Bugzilla 2000-08-31 15:57:55 UTC
Jakub, what do you think my patch? The problem is we cannot allocate edx
for DImode since eax/edx is a fixed pair for DImode. When we allocate
eax for DImode, we have implicitly allocated edx together with eax for DImode.
I don't know how to express it. That is what I came up with. There must be
a better fix.

Comment 10 Red Hat Bugzilla 2000-09-01 00:24:05 UTC
Created attachment 3158 [details]
A patch for find_reg ()

Comment 11 Red Hat Bugzilla 2000-09-01 00:29:27 UTC
Jakub, what do you think my new patch? The problem is
global_conflicts () is called before find_reg (). It
misses the hard register conflicts introduced by find_reg ().
I don't know if my patch is correct or not.

Comment 12 Red Hat Bugzilla 2000-09-01 14:58:08 UTC
Created attachment 3178 [details]
An updated patch for find_reg ().

Comment 13 Red Hat Bugzilla 2000-09-01 15:00:49 UTC
I updated my patch. I changed

if (reg && r >= 0 && r != regno && TEST_HARD_REG_BIT (used, r))

to

if (reg && r >= 0 && r < regno && TEST_HARD_REG_BIT (used, r))

since a hard register r >= regno won't overlap with regno.


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