gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-98)
breaks on complex expressions involving long long. Swapping two lines
in xfs_bmap.c works around the broken gcc.
For the record, this test gcc_bug.c file demonstrates the bug. Note
that it uses the standard do_div from /usr/include/asm/div64.h and not
the xfs version, although both versions of do_div fail with gcc 2.96.
I doubt that it is worth opening a bug with gcc, AFAICT they don't want
to know about 2.96, even the latest "fixed" RedHat version.
#define do_div(n,base) ({ \
unsigned long __upper, __low, __high, __mod; \
asm("":"=a" (__low), "=d" (__high):"A" (n)); \
__upper = __high; \
if (__high) { \
__upper = __high % (base); \
__high = __high / (base); \
} \
asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (base), "0" (__low), "1"
(__upper)); \
asm("":"=A" (n):"a" (__low),"d" (__high)); \
__mod; \
})
void gcc_bug(unsigned long long *len_p)
{
unsigned long long bno;
unsigned long long len;
bno = 2000;
do_div(bno, 12);
len = *len_p;
do_div(len, 24);
printf("%lld %lld\n", bno, len);
}
gcc -O2 gcc_bug.c
gcc_bug.c: In function `gcc_bug':
gcc_bug.c:26: Unrecognizable insn:
(insn 49 149 143 (parallel[
(set (reg:SI 0 eax)
(asm_operands ("") ("=a") 0[
(reg:DI 1 edx)
]
[
(asm_input:DI ("A"))
] ("gcc_bug.c") 24))
(set (reg:SI 1 edx)
(asm_operands ("") ("=d") 1[
(reg:DI 1 edx)
]
[
(asm_input:DI ("A"))
] ("gcc_bug.c") 24))
(clobber (reg:QI 19 dirflag))
(clobber (reg:QI 18 fpsr))
(clobber (reg:QI 17 flags))
] ) -1 (insn_list 45 (nil))
(nil))
gcc_bug.c:26: confused by earlier errors, bailing out
Setting both bno and len before do_div works, i.e.
bno = 2000;
len = *len_p;
do_div(bno, 12);
do_div(len, 24);
Date: Thu Jan 10 00:03:03 PST 2002
Workarea: sherman.melbourne.sgi.com:/build/kaos/2.4.x-xfs
The following file(s) were checked into:
bonnie.engr.sgi.com:/isms/slinx/2.4.x-xfs
Modid: 2.4.x-xfs:slinx:109353a
linux/fs/xfs/xfs_bmap.c - 1.279
|