weird code generation differences without optimization [was Re: purify 4.1 and egcs still appear to be incompatible.]

Ian Haggard ian@shellus.com
Tue Feb 17 11:20:00 GMT 1998


Brad M. Garcia wrote:
> 
> On Mon, 16 Feb 1998, Ian Haggard wrote:
> 
> > Actually, the problem is that gcc's default copy constructors for "empty" types
> > somehow are making purify think that the one byte being copied is actually
> > being used.
> 
> So... why does gcc copy a random byte unnecessarily?  I would think that
> we could at least change it to copy something that _has_ been initialized.
> Or make it do something other than a copy.  I'm assuming that this "null"
> instruction has been added to assist debugging in some way.
The reason for the "unnecessary" copy is that the default copy ctor/assignment
op are defined simply to do bitwise copy.  And the standard, unfortunately,
also requires that even "empty" structs take up space.

Hmmm...the more I look at this, the weirder it gets.  My example program in my
previous message suddenly started giving me purify errors all the time, not
just when I was defining NO_PURIFY_ERROR.  But now check this out:


triton:tests% cat truetype3.cc

struct __true_type {
};

template <class T>
inline void tifoo(T) {}

template<class T>
void tfoo(T) {}

inline void ifoo(__true_type) {}
void foo(__true_type) {}

main() {
  tifoo(__true_type());
  tfoo(__true_type());
  ifoo(__true_type());
  foo(__true_type());
  return 0;
}

triton:tests% g++ -v
Reading specs from
/////////////////////home/discovery4/ian/pkg/egcs-1.0/sparc-sun-solaris2.5.1/lib/gcc-lib/sparc-sun-solaris2.5.1/egcs-2.90.21/specs
gcc version egcs-2.90.21 971202 (egcs-1.00 release)
triton:tests% purify g++ truetype3.cc -o truetype3
Purify 4.1 Solaris 2, Copyright (C) 1992-1997 Rational Software Corp. All
rights reserved. 
Instrumenting: cca003ib1.o libgcc.a.....
Purify engine: While processing file
/home/triton2/ian/pkg/gcc-2.8.0/sparc-sun-solaris2.5.1/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/libgcc.a(_bb.o):
Warning: Found untested reloc type R_SPARC_GOT10 at location 0x1480 (section
2),
apparently pointing to offset 0x28.
[SNIP more R_SPARC_GOT10 warnings]
Purify engine: Warning: Found untested reloc type R_SPARC_GOT10 at location
0x1b80 (section 2),
apparently pointing to offset 0xc0.
................................................  Linking
triton:tests% ./truetype3
****  Purify instrumented ./truetype3 (pid 15292 at Tue Feb 17 12:30:55 1998)
  * Purify 4.1 Solaris 2, Copyright (C) 1992-1997 Rational Software Corp. All
rights reserved. 
  * For contact information type: "purify -help"
  * For Purify Viewer output, set the DISPLAY environment variable.
  * Command-line: ./truetype3 
  * Options settings: -cache-dir=/home/enterprise4/casper/cache \
    -always-use-cache-dir \
    -purify_home=/home/brclib7/software/pure/purify-4.1-solaris2 \
    -recursion-depth-limit=20000 \
    -cache-dir=/home/discovery4/ian/homes/localdisk/purelibcache -g++=yes \
    -purify -purify-home=/home/brclib7/software/pure/purify-4.1-solaris2 
  * Purify licensed to Shell Development Co. or Shell Development Company or
SHELL E&P TECHNOLOGY
  * Purify checking enabled.

****  Purify instrumented ./truetype3 (pid 15292)  ****
UMR: Uninitialized memory read:
  * This is occurring while in:
        tifoo__H1Z11__true_type_X01_v [cca003ib1.o]
        main           [cca003ib1.o]
        _start         [crt1.o]
  * Reading 1 byte from 0xeffff4c7 on the stack.
  * Address 0xeffff4c7 is 17 bytes below frame pointer in function main.

****  Purify instrumented ./truetype3 (pid 15292)  ****
UMR: Uninitialized memory read:
  * This is occurring while in:
        ifoo(__true_type) [cca003ib1.o]
        main           [cca003ib1.o]
        _start         [crt1.o]
  * Reading 1 byte from 0xeffff4c7 on the stack.
  * Address 0xeffff4c7 is 17 bytes below frame pointer in function main.

****  Purify instrumented ./truetype3 (pid 15292)  ****
Current file descriptors in use: 6
FIU: file descriptor 0: <stdin>
FIU: file descriptor 1: <stdout>
FIU: file descriptor 2: <stderr>
FIU: file descriptor 3: <inherited from parent>
FIU: file descriptor 26: <reserved for Purify internal use>
FIU: file descriptor 27: <reserved for Purify internal use>

No dynamic memory is in use.  No leaks are possible.

****  Purify instrumented ./truetype3 (pid 15292)  ****
  * Program exited with status code 0.
  * 2 access errors, 2 total occurrences.
  * Basic memory usage (including Purify overhead):
      292988 code
       79284 data/bss
           0 heap (peak use)
        2856 stack
  * Shared library memory usage (including Purify overhead):
      135713 libm.so.1_pure_p3_c0_410_551 (shared code)
        5872 libm.so.1_pure_p3_c0_410_551 (private data)
      803345 libc.so.1_pure_p3_c0_410_551 (shared code)
       34868 libc.so.1_pure_p3_c0_410_551 (private data)
        1216 libdl.so.1_pure_p3_c0_410_551 (shared code)
           0 libdl.so.1_pure_p3_c0_410_551 (private data)
        9576 libinternal_stubs.so.1 (shared code)
         324 libinternal_stubs.so.1 (private data)

triton:tests% 


So only the inline versions of the function produce the purify errors.  And
when I took a look at the assembly code, I understood why.  The out-of-line
versions only did some register moves, but the inline versions actually loaded
the value of their argument into a register.  Moreover, the non-template
versions contained two useless unconditional branch instructions at the end of
the function.  I'm attaching the .s-file generated by egcs-1.0 from the above
source code.  Could someone please explain to me the reason why each version of
this empty function generates different assembly?  BTW, in when I compiled my
test file with gcc 2.7.0, all of the functions generated the same code, which
was of the form:


foo__FG11__true_type:
        !#PROLOGUE# 0
        save %sp,-112,%sp
        !#PROLOGUE# 1
        mov %i0,%o0
        b .LL4
        nop
        b .LL3
        nop
.LL4:
.LL3:
        ret
        restore


I still don't understand why the unconditional branches are necessary, but the
code generation is consistent, anyway.
--
Ian Haggard  ||  ian@shellus.com (work)  ||  IanHaggard@juno.com (home)
GNU/Linux -- "Oh, no, Mr Bill!" || #define employer_opinion !my_opinion
	.file	"truetype3.cc"
! GNU C++ version egcs-2.90.21 971202 (egcs-1.00 release) (sparc-sun-solaris2.5.1) compiled by GNU C version 2.7.0.
! options passed: 
! options enabled:  -fpeephole -ffunction-cse -fkeep-static-consts
! -fpcc-struct-return -fexceptions -fcommon -fverbose-asm -fgnu-linker
! -fargument-alias -mepilogue -mapp-regs

gcc2_compiled.:
.section	".text"
	.align 4
	.global foo__FG11__true_type
	.type	 foo__FG11__true_type,#function
	.proc	020
foo__FG11__true_type:
.LLFB1:
	!#PROLOGUE# 0
	save %sp,-112,%sp
.LLCFI0:
	!#PROLOGUE# 1
	mov %i0,%o0
	b .LL4
	nop
	b .LL3
	nop
.LL4:
.LL3:
	ret
	restore
.LLFE1:
.LLfe1:
	.size	 foo__FG11__true_type,.LLfe1-foo__FG11__true_type
	.align 4
	.global main
	.type	 main,#function
	.proc	04
main:
.LLFB2:
	!#PROLOGUE# 0
	save %sp,-120,%sp
.LLCFI1:
	!#PROLOGUE# 1
	add %fp,-17,%o1
	mov %o1,%o0
	call __11__true_type,0
	nop
	add %fp,-17,%o1
	mov %o1,%o0
	call tifoo__H1Z11__true_type_X01_v,0
	nop
	add %fp,-17,%o1
	mov %o1,%o0
	call __11__true_type,0
	nop
	add %fp,-17,%o1
	mov %o1,%o0
	call tfoo__H1Z11__true_type_X01_v,0
	nop
	add %fp,-17,%o1
	mov %o1,%o0
	call __11__true_type,0
	nop
	add %fp,-17,%o1
	mov %o1,%o0
	call ifoo__FG11__true_type,0
	nop
	add %fp,-17,%o1
	mov %o1,%o0
	call __11__true_type,0
	nop
	add %fp,-17,%o1
	mov %o1,%o0
	call foo__FG11__true_type,0
	nop
	mov 0,%i0
	b .LL5
	nop
	mov 0,%i0
	b .LL5
	nop
.LL5:
	ret
	restore
.LLFE2:
.LLfe2:
	.size	 main,.LLfe2-main
.section	".gnu.linkonce.t.tfoo__H1Z11__true_type_X01_v",#alloc,#execinstr
	.align 4
	.weak	tfoo__H1Z11__true_type_X01_v
	.type	 tfoo__H1Z11__true_type_X01_v,#function
	.proc	020
tfoo__H1Z11__true_type_X01_v:
.LLFB3:
	!#PROLOGUE# 0
	save %sp,-112,%sp
.LLCFI2:
	!#PROLOGUE# 1
	mov %i0,%o0
.LL9:
	ret
	restore
.LLFE3:
.LLfe3:
	.size	 tfoo__H1Z11__true_type_X01_v,.LLfe3-tfoo__H1Z11__true_type_X01_v
.section	".gnu.linkonce.t.tifoo__H1Z11__true_type_X01_v",#alloc,#execinstr
	.align 4
	.weak	tifoo__H1Z11__true_type_X01_v
	.type	 tifoo__H1Z11__true_type_X01_v,#function
	.proc	020
tifoo__H1Z11__true_type_X01_v:
.LLFB4:
	!#PROLOGUE# 0
	save %sp,-112,%sp
.LLCFI3:
	!#PROLOGUE# 1
	mov %i0,%o1
	ldub [%o1],%o0
.LL8:
	ret
	restore
.LLFE4:
.LLfe4:
	.size	 tifoo__H1Z11__true_type_X01_v,.LLfe4-tifoo__H1Z11__true_type_X01_v
.section	".gnu.linkonce.t.ifoo__FG11__true_type",#alloc,#execinstr
	.align 4
	.weak	ifoo__FG11__true_type
	.type	 ifoo__FG11__true_type,#function
	.proc	020
ifoo__FG11__true_type:
.LLFB5:
	!#PROLOGUE# 0
	save %sp,-112,%sp
.LLCFI4:
	!#PROLOGUE# 1
	mov %i0,%o1
	ldub [%o1],%o0
	b .LL2
	nop
	b .LL1
	nop
.LL2:
.LL1:
	ret
	restore
.LLFE5:
.LLfe5:
	.size	 ifoo__FG11__true_type,.LLfe5-ifoo__FG11__true_type
.section	".gnu.linkonce.t.__11__true_type",#alloc,#execinstr
	.align 4
	.weak	__11__true_type
	.type	 __11__true_type,#function
	.proc	0110
__11__true_type:
.LLFB6:
	!#PROLOGUE# 0
	save %sp,-112,%sp
.LLCFI5:
	!#PROLOGUE# 1
	mov %i0,%o0
.LL7:
	mov %o0,%i0
	b .LL6
	nop
.LL6:
	ret
	restore
.LLFE6:
.LLfe6:
	.size	 __11__true_type,.LLfe6-__11__true_type

.section	".eh_frame",#alloc,#write
__FRAME_BEGIN__:
	.uaword	.LLECIE1-.LLSCIE1
.LLSCIE1:
	.uaword	0x0
	.byte	0x1
	.byte	0x0
	.byte	0x1
	.byte	0x7c
	.byte	0x65
	.byte	0xc
	.byte	0xe
	.byte	0x0
	.byte	0x9
	.byte	0x65
	.byte	0xf
	.align 4
.LLECIE1:
	.uaword	.LLEFDE1-.LLSFDE1
.LLSFDE1:
	.uaword	.LLSFDE1-__FRAME_BEGIN__
	.uaword	.LLFB1
	.uaword	.LLFE1-.LLFB1
	.byte	0x4
	.uaword	.LLCFI0-.LLFB1
	.byte	0xd
	.byte	0x1e
	.byte	0x2d
	.byte	0x9
	.byte	0x65
	.byte	0x1f
	.align 4
.LLEFDE1:
	.uaword	.LLEFDE3-.LLSFDE3
.LLSFDE3:
	.uaword	.LLSFDE3-__FRAME_BEGIN__
	.uaword	.LLFB2
	.uaword	.LLFE2-.LLFB2
	.byte	0x4
	.uaword	.LLCFI1-.LLFB2
	.byte	0xd
	.byte	0x1e
	.byte	0x2d
	.byte	0x9
	.byte	0x65
	.byte	0x1f
	.align 4
.LLEFDE3:
	.uaword	.LLEFDE5-.LLSFDE5
.LLSFDE5:
	.uaword	.LLSFDE5-__FRAME_BEGIN__
	.uaword	.LLFB3
	.uaword	.LLFE3-.LLFB3
	.byte	0x4
	.uaword	.LLCFI2-.LLFB3
	.byte	0xd
	.byte	0x1e
	.byte	0x2d
	.byte	0x9
	.byte	0x65
	.byte	0x1f
	.align 4
.LLEFDE5:
	.uaword	.LLEFDE7-.LLSFDE7
.LLSFDE7:
	.uaword	.LLSFDE7-__FRAME_BEGIN__
	.uaword	.LLFB4
	.uaword	.LLFE4-.LLFB4
	.byte	0x4
	.uaword	.LLCFI3-.LLFB4
	.byte	0xd
	.byte	0x1e
	.byte	0x2d
	.byte	0x9
	.byte	0x65
	.byte	0x1f
	.align 4
.LLEFDE7:
	.uaword	.LLEFDE9-.LLSFDE9
.LLSFDE9:
	.uaword	.LLSFDE9-__FRAME_BEGIN__
	.uaword	.LLFB5
	.uaword	.LLFE5-.LLFB5
	.byte	0x4
	.uaword	.LLCFI4-.LLFB5
	.byte	0xd
	.byte	0x1e
	.byte	0x2d
	.byte	0x9
	.byte	0x65
	.byte	0x1f
	.align 4
.LLEFDE9:
	.uaword	.LLEFDE11-.LLSFDE11
.LLSFDE11:
	.uaword	.LLSFDE11-__FRAME_BEGIN__
	.uaword	.LLFB6
	.uaword	.LLFE6-.LLFB6
	.byte	0x4
	.uaword	.LLCFI5-.LLFB6
	.byte	0xd
	.byte	0x1e
	.byte	0x2d
	.byte	0x9
	.byte	0x65
	.byte	0x1f
	.align 4
.LLEFDE11:
	.ident	"GCC: (GNU) egcs-2.90.21 971202 (egcs-1.00 release)"


More information about the Gcc-bugs mailing list