This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/29319] ICE unrecognizable insn: offset too large for larl (breaks glibc)
- From: "matz at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 2 Oct 2006 11:35:55 -0000
- Subject: [Bug target/29319] ICE unrecognizable insn: offset too large for larl (breaks glibc)
- References: <bug-29319-12182@http.gcc.gnu.org/bugzilla/>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Comment #2 from matz at gcc dot gnu dot org 2006-10-02 11:35 -------
Note that with this patch solves the bug for this testcase, but it still
doesn't help with the general case. With this slightly changed testcase:
% cat large-ofs2.c
static char l_info[100];
void bug1 (unsigned long tag)
{
char *info = l_info;
info[tag - 0x100000000 + 1] = 1;
}
void bug2 (unsigned long tag)
{
char *info = l_info;
info[tag - 0x100000000 + 1] = 2;
}
extern void abort();
int main()
{
unsigned i;
for (i = 0; i < sizeof(l_info); i++)
l_info[i] = 0;
bug1(0x100000000);
bug2(0x100000000);
if (l_info[2] != 2 || l_info[1] != 1)
abort();
return 0;
}
% gcc -S -O2 -fPIC -march=z9-109 large-ofs2.c
% gcc large-ofs2.s
large-ofs2.s: Assembler messages:
large-ofs2.s:19: Error: value of -4294967312 too large for field of 4 bytes at
18
Note how the bodies of both functions is exactly the same, but still it
only fails in the second function. For reference here the asm of both
functions:
6 bug1:
7 .LFB2:
8 larl %r1,l_info-4294967296
9 lhi %r3,1
10 stc %r3,1(%r2,%r1)
11 br %r14
12 .LFE2:
13 .size bug1, .-bug1
14 .align 4
15 .globl bug2
16 .type bug2, @function
17 bug2:
18 .LFB3:
19 larl %r1,l_info-4294967296
20 lhi %r3,2
21 stc %r3,1(%r2,%r1)
22 br %r14
I assume the reason is, that the assembler somehow calculates this pc
relative. In that case it could also break later during linking if the
linker doesn't have special means to fix up too large offsets.
So, I think s390x is in the same situation as x86-64. We can't allow
large constant offsets on objects, even though instructions might accept
them, because the object might become placed just a bit too far away,
so that it's base is still in reach, while the offset added to it is not
anymore. On x86-64 we solve that by artificially constraining the range
of offsets. That should perhaps be done here too. E.g. by using
DISP_IN_RANGE instead of the </>= test I copied from larl_operand.
Up to the maintainers.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29319