Bug 39810

Summary: gcc-c++-2.96-81 inadequate optimization
Product: [Retired] Red Hat Linux Reporter: Omnifarious <hopper>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED RAWHIDE QA Contact: David Lawrence <dkl>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.0Keywords: FutureFeature
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Enhancement
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2001-05-09 10:21:44 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:
Attachments:
Description Flags
This is an example C++ source file that compiles with bloated initializers none

Description Omnifarious 2001-05-09 06:35:44 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux 2.4.3 i686; en-US; 0.8.1) Gecko/20010421

Description of problem:
Static initializers are optimized very poorly.  Jump optimization seems not
to be performed, and when the initializers have a result that can be
verified as static at compile time, they are not removed and simply set up
as constant values in the .rodata or .data section.


How reproducible:
Always

Steps to Reproduce:
1.g++ -pipe -march=athlon -O2 -S example.cpp

2.Examine example.s.	

Actual Results:  	.file	"example.cpp"
	.version	"01.01"
gcc2_compiled.:
.globl abarney
.bss
	.align 4
	.type	 abarney,@object
	.size	 abarney,8
abarney:
	.zero	8
.globl afred
	.align 4
	.type	 afred,@object
	.size	 afred,4
afred:
	.zero	4
.text
	.align 16
	.type	 __static_initialization_and_destruction_0,@function
__static_initialization_and_destruction_0:
.LFB1:
	pushl	%ebp
.LCFI0:
	movl	%esp, %ebp
.LCFI1:
	movl	12(%ebp), %eax
	movl	8(%ebp), %edx
	cmpl	$65535, %eax
	jne	.L3
	cmpl	$1, %edx
	jne	.L3
	movl	$5, abarney
	movl	$6, abarney+4
.L3:
	cmpl	$65535, %eax
	jne	.L11
	decl	%edx
	jne	.L11
	movl	$2, afred
.L11:
	popl	%ebp
	ret
.LFE1:
.Lfe1:
	.size	
__static_initialization_and_destruction_0,.Lfe1-__static_initialization_and_destruction_0
	.align 16
	.type	 _GLOBAL_.I.abarney,@function
_GLOBAL_.I.abarney:
.LFB2:
	pushl	%ebp
.LCFI2:
	movl	%esp, %ebp
.LCFI3:
	subl	$16, %esp
.LCFI4:
	pushl	$65535
	pushl	$1
.LCFI5:
	call	__static_initialization_and_destruction_0
	addl	$16, %esp
	leave
	ret
.LFE2:
.Lfe2:
	.size	 _GLOBAL_.I.abarney,.Lfe2-_GLOBAL_.I.abarney
		.section	.ctors,"aw"
	.long	 _GLOBAL_.I.abarney
	.ident	"GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)"



Expected Results:  	.file	"example2.cpp"
	.version	"01.01"
gcc2_compiled.:
.globl abarney
		.section	.rodata
	.align 4
	.type	 abarney,@object
	.size	 abarney,8
abarney:
	.long	5
	.long	6
.globl afred
	.align 4
	.type	 afred,@object
	.size	 afred,4
afred:
	.long	2
	.ident	"GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)"



Additional info:

example.cpp:
class Fred {
   public:
      Fred(int x) : x_(x) { }

   private:
      int x_;
};

class Barney : public Fred {
   public:
      Barney(int x, int y) : Fred(x), y_(y) { }

   private:
      int y_;
};

extern const Barney abarney(5, 6);
extern const Fred afred(2);
------------
The results of all these initializers can be statically determined at
compile time.  There is no reason I can think of they should be stuck in
the .rodata section.  If they were not const, they could be stuck in the
.data section.

Even if the initializer is run, the initializer itself will make repeated
comparisons of %eax against $65535 instead of simply jumping to the end if
the first such comparison registers as being equal.  This situation is also
easily determined by simple analysis, and jump optimization in ordinary
code would catch it.

Comment 1 Omnifarious 2001-05-09 06:36:59 UTC
Created attachment 17827 [details]
This is an example C++ source file that compiles with bloated initializers

Comment 2 Jakub Jelinek 2001-05-09 10:21:39 UTC
As for eliminating the static initializers, ATM none of g++ 2.95.x, 2.96-RH,
3.0-branch or 3.1-head do this. It would be probably better if you requested
this enhancement on @gnu.org lists (it is too late for 3.0, but for 3.1 it could be doable).
As for the jump to test+jump not being optimized out, I'll look at what's going
on. It seems that gcc 3.0 and 3.1 behave the same way, have reproduced it
on C code as well:
int abarney[2];
int afred[1];

void foo(int edx, int eax)
{
  if (eax == 65535)
    {
      if (edx == 1)
        {
          abarney[0] = 5;
          abarney[1] = 6;
        }
    }
  if (eax == 65535)
    {
      if (--edx == 0)
        afred[0] = 2;
    }
}

Comment 3 Jakub Jelinek 2001-06-07 13:07:42 UTC
Jump threading should be fixed in gcc-2.96-86, likewise it will generate
better code for __static_initialization_and_destruction_0 (which even
jump threading is not able to cope with).

Comment 4 Omnifarious 2001-06-27 06:18:41 UTC
Thanks, in gcc-c++-2.96-88, this is now lots better than it was.  :-)

I still say the constructors can be done away with completely and the constant
initial values moved into the .bss segment, but I imagine that's kind of hard to do.

It would solve a major class of problems dealing with order of static
intialization though.  I wouldn't have to worry about initialization order for
many types of global constants.