[gnu.g++.bug] optimization blues

rjc@CS.UCLA.EDU (Robert Collins) (10/28/89)

Sun4/300, SunOS 4.0.3, g++ Oct 17

Not a bug report--just a question:  This is optimized code?

I compiled with -O and -S only.  The output looks *quite* sub-optimal to
my untrained eye.  I would especially like to see the conditional in +=
to be evaluated at compile-time.  This would allow the removal of the
test and branch of the conditional that is not used.

This sort of optimization would make me happy.  This would reduce my
run-time and cut my object files to a fraction of their current size!
(I have *lots* of code that does this sort of thing)  Is there any
chance for this sort of agressive optimization?  Am I dreaming the
impossible dream?  Do I need to declare more things const??

Sub-optimally yours,
rob collins
rjc@cs.ucla.edu

---------------------------------------------------------------------------
extern "C" {
    typedef int CM_field_id_t;
    CM_field_id_t CM_allocate_heap_field(unsigned);
    void CM_deallocate_heap_field(CM_field_id_t);
    void CM_s_add_2_1L(CM_field_id_t d, CM_field_id_t s, unsigned l);
    void CM_s_add_3_3L(CM_field_id_t d, CM_field_id_t s1, CM_field_id_t s2,
		       unsigned dl, unsigned s1l, unsigned s2l);
};

class CM_int;

void CM_add(const CM_int& dest, const CM_int& source);

class CM_int {
  private:
    const CM_field_id_t the_field;
    const unsigned the_length;

  public:
    CM_int(unsigned l);
    ~CM_int(void);

    unsigned length(void) const;
    operator CM_field_id_t() const;
    void operator+=(const CM_int&);
};

inline CM_int::CM_int(unsigned l) : the_length(l),
    the_field(CM_allocate_heap_field(the_length))
{
}

inline CM_int::~CM_int(void)
{
    CM_deallocate_heap_field(the_field);
}

inline unsigned CM_int::length(void) const
{
    return the_length;
}

inline CM_int::operator CM_field_id_t() const
{
    return the_field;
}

inline void CM_int::operator+=(const CM_int& rhs)
{
    //CM_add(*this, rhs);
    if (length() == rhs.length()) {
	CM_s_add_2_1L(*this, rhs, length());
    }
    else {
	CM_s_add_3_3L(*this, *this, rhs, length(), length(),
		      rhs.length());
    };
}

inline void CM_add(const CM_int& dest, const CM_int& source)
{
    if (dest.length() == source.length()) {
	CM_s_add_2_1L(dest, source, dest.length());
    }
    else {
	CM_s_add_3_3L(dest, dest, source, dest.length(), dest.length(),
		      source.length());
    };
}

main()
{
    CM_int a(32), b(32);
    a += b;
    CM_int c(32), d(16);
    c += d;
}
---------------------------------------------------------------------------
gcc_compiled.:
.text
	.align 4
.global _main
	.proc 1
_main:
	!#PROLOGUE# 0
	save %sp,-144,%sp
	!#PROLOGUE# 1
	call ___main,0
	nop
	add %fp,-24,%l0
	mov 32,%l2
	st %l2,[%l0+4]
	call _CM_allocate_heap_field,0
	mov 32,%o0
	st %o0,[%l0]
	add %fp,-32,%l1
	mov 32,%l2
	st %l2,[%l1+4]
	call _CM_allocate_heap_field,0
	mov 32,%o0
	mov %o0,%o1
	st %o1,[%l1]
	mov %l0,%o2
	mov %l1,%o5
	ld [%o2+4],%o3
	ld [%o5+4],%o0
	cmp %o3,%o0
	bne L75
	nop
	ld [%o2],%o0
	call _CM_s_add_2_1L,0
	mov %o3,%o2
	b,a L74
L75:
	ld [%o2],%o1
	ld [%o2+4],%o4
	mov %o1,%o0
	ld [%o5],%o2
	mov %o4,%o3
	call _CM_s_add_3_3L,0
	ld [%o5+4],%o5
L74:
	add %fp,-40,%l0
	mov 32,%l2
	st %l2,[%l0+4]
	call _CM_allocate_heap_field,0
	mov 32,%o0
	st %o0,[%l0]
	add %fp,-48,%l1
	mov 16,%l2
	st %l2,[%l1+4]
	call _CM_allocate_heap_field,0
	mov 16,%o0
	mov %o0,%o1
	st %o1,[%l1]
	mov %l0,%o2
	mov %l1,%o5
	ld [%o2+4],%o3
	ld [%o5+4],%o0
	cmp %o3,%o0
	bne L91
	nop
	ld [%o2],%o0
	call _CM_s_add_2_1L,0
	mov %o3,%o2
	b,a L90
L91:
	ld [%o2],%o1
	ld [%o2+4],%o4
	mov %o1,%o0
	ld [%o5],%o2
	mov %o4,%o3
	call _CM_s_add_3_3L,0
	ld [%o5+4],%o5
L90:
	call _CM_deallocate_heap_field,0
	ld [%fp-48],%o0
	call _CM_deallocate_heap_field,0
	ld [%fp-40],%o0
	call _CM_deallocate_heap_field,0
	ld [%fp-32],%o0
	call _CM_deallocate_heap_field,0
	ld [%fp-24],%o0
	mov 0,%i0
	ret
	restore
---------------------------------------------------------------------------