Bug 85873

Summary: Optimized -march=i686 can generate bad ?: code
Product: [Retired] Red Hat Linux Reporter: Need Real Name <richard>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED CURRENTRELEASE QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.3   
Target Milestone: ---   
Target Release: ---   
Hardware: i686   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2004-10-03 12:50:43 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

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:

////////bugfuncs.hh:
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;
};

////////bugfuncs.cc:
#include "bugfuncs.hh"

void
bar_t::bug()
{
  double d[5];
  const int n = N;
  const int& ab = Foo.pick(n);
  const int abcopy = ab;
  for (int i = 1; i < n; ++i)
    use(abcopy*i);
  d[n] = 0.0;
  use(ab);
}

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

////////bugmain.cc:
#include "bugfuncs.hh"

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

////////GNUmakefile:
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.]
////////bugfuncs.s:
	.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

gcc2_compiled.:
.text
	.align 16
.globl bug__5bar_t
	.type	 bug__5bar_t,@function
bug__5bar_t:
.LFB1:
	pushl	%ebp
.LCFI0:
	movl	%esp, %ebp
.LCFI1:
	pushl	%edi
.LCFI2:
	pushl	%esi
.LCFI3:
	pushl	%ebx
.LCFI4:
	subl	$76, %esp
.LCFI5:
	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
.L8:
	subl	$12, %esp
	pushl	%esi
.LCFI6:
	call	use__5bar_ti
	addl	$16, %esp
	addl	%edi, %esi
	decl	%ebx
	jne	.L8
.L20:
	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
	ret
.LFE1:
.Lfe1:
	.size	 bug__5bar_t,.Lfe1-bug__5bar_t
	.align 16
.globl zero__5bar_t
	.type	 zero__5bar_t,@function
zero__5bar_t:
.LFB2:
	pushl	%ebp
.LCFI7:
	movl	%esp, %ebp
.LCFI8:
	movl	$31, %edx
	subl	$136, %esp
.LCFI9:
	leal	-12(%ebp), %eax
	.p2align 4
.L15:
	movl	$0, (%eax)
	subl	$4, %eax
	decl	%edx
	jns	.L15
	movl	%ebp, %esp
	popl	%ebp
	ret
.LFE2:
.Lfe2:
	.size	 zero__5bar_t,.Lfe2-zero__5bar_t
	.align 16
.globl use__5bar_ti
	.type	 use__5bar_ti,@function
use__5bar_ti:
.LFB3:
	pushl	%ebp
.LCFI10:
	movl	%esp, %ebp
.LCFI11:
	popl	%ebp
	ret
.LFE3:
.Lfe3:
	.size	 use__5bar_ti,.Lfe3-use__5bar_ti

	.section	.eh_frame,"aw",@progbits
__FRAME_BEGIN__:
	.4byte	.LLCIE1
.LSCIE1:
	.4byte	0x0
	.byte	0x1
	.byte	0x0
	.byte	0x1
	.byte	0x7c
	.byte	0x8
	.byte	0xc
	.byte	0x4
	.byte	0x4
	.byte	0x88
	.byte	0x1
	.align 4
.LECIE1:
	.set	.LLCIE1,.LECIE1-.LSCIE1
	.4byte	.LLFDE1
.LSFDE1:
	.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
.LEFDE1:
	.set	.LLFDE1,.LEFDE1-.LSFDE1
	.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:
Always
(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?