Bug 85873 - Optimized -march=i686 can generate bad ?: code
Summary: Optimized -march=i686 can generate bad ?: code
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: gcc
Version: 7.3
Hardware: i686
OS: Linux
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Brian Brock
Depends On:
TreeView+ depends on / blocked
Reported: 2003-03-10 00:17 UTC by Need Real Name
Modified: 2007-04-18 16:51 UTC (History)
0 users

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Last Closed: 2004-10-03 12:50:43 UTC

Attachments (Terms of Use)

Description Need Real Name 2003-03-10 00:17:49 UTC
From Bugzilla Helper:
User-Agent: Mozilla/4.79 [en] (X11; U; IRIX64 6.5 IP30)

Description of problem:
The g++ 2.96 compiler will occasionally produce bad code for
the 'test ? expr1 : expr2' operator when optimizing with
'-march=i686' or '-march=pentiumpro'.

Consider this sample source code:

struct foo_t
  inline const int& pick(int i) const { return i ? B : A; }
  int A;
  int B;

struct bar_t
  inline bar_t(int n): N(n) {}
  void bug();
  static void zero();
  static void use(int);
  int N;
  foo_t Foo;

#include "bugfuncs.hh"

  double d[5];
  const int n = N;
  const int& ab = Foo.pick(n);
  const int abcopy = ab;
  for (int i = 1; i < n; ++i)
  d[n] = 0.0;

void bar_t::zero() { int a[32]; for (int i = 0; i < 32; ++i) a[i] = 0; }
void bar_t::use(int) {}

#include "bugfuncs.hh"

int main(int argc, char **)
  bar_t bar((argc-1) & 1);
  return bar.N;

bug: bugmain.cc bugfuncs.cc bugfuncs.hh;g++ -O3 -march=pentiumpro -fverbose-asm
-save-temps -o bug bugmain.cc bugfuncs.cc

When compiled and run, ./bug should exit with 0.  However,
because of a code generation bug in the optimizer, it fails
with a segmentation fault.  However, with small changes to
the code, the bug may disappear.

Here is the code generated for bugfuncs.cc:
[Note it particular that the 'cmove -80(%ebp), %eax'
instruction following .LCFI5 is the first access to
'-80(%ebp)', so when %ebx is zero the value used has
not be properly initialized.]
	.file	"bugfuncs.cc"
	.version	"01.01"
# GNU C++ version 2.96 20000731 (Red Hat Linux 7.3 2.96-113) (i386-redhat-linux)
compiled by GNU C version 2.96 20000731 (Red Hat Linux 7.3 2.96-113).
# options passed:  -march=pentiumpro -O3 -fverbose-asm
# options enabled:  -fdefer-pop -foptimize-sibling-calls -fcse-follow-jumps
# -fcse-skip-blocks -fexpensive-optimizations -fthread-jumps
# -fstrength-reduce -fpeephole -fforce-mem -ffunction-cse
# -finline-functions -finline -fkeep-static-consts -fcaller-saves
# -fpcc-struct-return -fgcse -frerun-cse-after-loop -frerun-loop-opt
# -fdelete-null-pointer-checks -fschedule-insns2 -fsched-interblock
# -fsched-spec -fbranch-count-reg -fexceptions -fnew-exceptions -fcommon
# -fverbose-asm -fgnu-linker -fregmove -foptimize-register-move
# -fargument-alias -fstrict-aliasing -fmerge-constants -fident -fpeephole2
# -fmath-errno -m80387 -mhard-float -mno-soft-float -mieee-fp
# -mfp-ret-in-387 -march=pentiumpro

	.align 16
.globl bug__5bar_t
	.type	 bug__5bar_t,@function
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%edi
	pushl	%esi
	pushl	%ebx
	subl	$76, %esp
	movl	8(%ebp), %edx
	movl	(%edx), %eax
	movl	%eax, -76(%ebp)
	leal	8(%edx), %eax
	movl	-76(%ebp), %ebx
	testl	%ebx, %ebx
	cmove	-80(%ebp), %eax
	cmpl	$1, -76(%ebp)
	movl	%eax, -80(%ebp)
	movl	(%eax), %edi
	jle	.L20
	movl	-76(%ebp), %ebx
	movl	%edi, %esi
	decl	%ebx
	.p2align 4
	subl	$12, %esp
	pushl	%esi
	call	use__5bar_ti
	addl	$16, %esp
	addl	%edi, %esi
	decl	%ebx
	jne	.L8
	movl	-76(%ebp), %edx
	leal	-72(%ebp), %eax
	xorl	%ecx, %ecx
	subl	$12, %esp
	movl	$0, (%eax,%edx,8)
	movl	%ecx, 4(%eax,%edx,8)
	movl	-80(%ebp), %eax
	movl	(%eax), %eax
	pushl	%eax
	call	use__5bar_ti
	addl	$16, %esp
	leal	-12(%ebp), %esp
	popl	%ebx
	popl	%esi
	popl	%edi
	popl	%ebp
	.size	 bug__5bar_t,.Lfe1-bug__5bar_t
	.align 16
.globl zero__5bar_t
	.type	 zero__5bar_t,@function
	pushl	%ebp
	movl	%esp, %ebp
	movl	$31, %edx
	subl	$136, %esp
	leal	-12(%ebp), %eax
	.p2align 4
	movl	$0, (%eax)
	subl	$4, %eax
	decl	%edx
	jns	.L15
	movl	%ebp, %esp
	popl	%ebp
	.size	 zero__5bar_t,.Lfe2-zero__5bar_t
	.align 16
.globl use__5bar_ti
	.type	 use__5bar_ti,@function
	pushl	%ebp
	movl	%esp, %ebp
	popl	%ebp
	.size	 use__5bar_ti,.Lfe3-use__5bar_ti

	.section	.eh_frame,"aw",@progbits
	.4byte	.LLCIE1
	.4byte	0x0
	.byte	0x1
	.byte	0x0
	.byte	0x1
	.byte	0x7c
	.byte	0x8
	.byte	0xc
	.byte	0x4
	.byte	0x4
	.byte	0x88
	.byte	0x1
	.align 4
	.4byte	.LLFDE1
	.4byte	.LSFDE1-__FRAME_BEGIN__
	.4byte	.LFB1
	.4byte	.LFE1-.LFB1
	.byte	0x4
	.4byte	.LCFI0-.LFB1
	.byte	0xe
	.byte	0x8
	.byte	0x85
	.byte	0x2
	.byte	0x4
	.4byte	.LCFI1-.LCFI0
	.byte	0xd
	.byte	0x5
	.byte	0x4
	.4byte	.LCFI2-.LCFI1
	.byte	0x87
	.byte	0x3
	.byte	0x4
	.4byte	.LCFI3-.LCFI2
	.byte	0x86
	.byte	0x4
	.byte	0x4
	.4byte	.LCFI4-.LCFI3
	.byte	0x83
	.byte	0x5
	.byte	0x4
	.4byte	.LCFI6-.LCFI4
	.byte	0x2e
	.byte	0x10
	.align 4
	.ident	"GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.3 2.96-113)"

Version-Release number of selected component (if applicable):
gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-113)

How reproducible:
(in the sense that the supplied sample fails consistently)

Steps to Reproduce:
1. Create specified bugfuncs.hh, bugfuncs.cc,
   bugmain.cc, and GNUmakefile
2. gmake
3. ./bug

Actual Results:  ./bug fails with a segmentation fault

Expected Results:  ./bug should exit with 0

Additional info:

It does seem that this bug is fairly rare.  The various
extraneous code in the sample source code is there because
the bug happens to show up this way.

The bug seems to be related to how the optimizer generates
code for the Pentium Pro instruction set.  So, to avoid the
bug, it seems sufficient to avoid using '-march=pentiumpro'
or its equivalent '-march=i686'.  Unfortunately, this is the
most recent instruction set that gcc 2.96 supports in the
iX86 family.

Comment 1 Richard Henderson 2004-10-03 12:50:43 UTC
"Fixed" in gcc 3.2, in that gcc eliminates the ?: entirely.
Probably fixed for real, but you can't tell from this test case.

Comment 2 Need Real Name 2004-10-03 23:17:06 UTC
After 574, this is the only response?

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