Thread View: gnu.g++.lib.bug
3 messages
3 total messages
Started by Doug Lea
Thu, 26 Oct 1989 10:30
Re: lack of inline functions in libg++
Author: Doug Lea
Date: Thu, 26 Oct 1989 10:30
Date: Thu, 26 Oct 1989 10:30
126 lines
3240 bytes
3240 bytes
Michael said...
> Another solution to coding around the cost of function calls is to use
> a RISC workstantion where that cost is negligible
But this is only part of the story. The *primary* goal of inlining on
RISC machine like a SPARC is not really saving a cycle or two for the
function call, but rather `procedural integration'. If inlines reveal
to the compiler some important constraints, constants, etc., that make
further simplifications and optimizations possible, it can be a HUGE
win. Try this:
#include <builtin.h>
#include <stream.h>
class Vec1000000
{
float s[1000000];
public:
Vec1000000() {}
~Vec1000000() {}
int size();
float& sub(int i);
int ni_size(); // non-inline versions
float& ni_sub(int i);
virtual int v_size(); // virtual non-inline versions
virtual float& v_sub(int i);
};
inline int Vec1000000::size() { return 1000000; }
int Vec1000000::ni_size() { return 1000000; }
int Vec1000000::v_size() { return 1000000; }
inline float& Vec1000000::sub(int i) { return s[i]; }
float& Vec1000000::ni_sub(int i) { return s[i]; }
float& Vec1000000::v_sub(int i) { return s[i]; }
void fill(Vec1000000& v, float x)
{
for (int i = 0; i < v.size(); ++i) v.sub(i) = x;
}
void ni_fill(Vec1000000& v, float x)
{
for (int i = 0; i < v.ni_size(); ++i) v.ni_sub(i) = x;
}
void v_fill(Vec1000000& v, float x)
{
for (int i = 0; i < v.v_size(); ++i) v.v_sub(i) = x;
}
main()
{
Vec1000000 v;
start_timer(); fill(v, 1.0);
cout << "fill time = " << return_elapsed_time(0.0) << "\n";
start_timer(); ni_fill(v, 1.0);
cout << "ni_fill time = " << return_elapsed_time(0.0) << "\n";
start_timer(); v_fill(v, 1.0);
cout << "v_fill time = " << return_elapsed_time(0.0) << "\n";
}
g++ -g -O -fstrength-reduce -fdelayed-branch t1026.cc -lg++
Compilation finished at Thu Oct 26 05:51:39
(on a Sun4/110)
g.oswego.edu% a.out
fill time = 0.71
ni_fill time = 1.93
v_fill time = 4.41
g.oswego.edu% !!
a.out
fill time = 0.63
ni_fill time = 1.9
v_fill time = 3.58
g.oswego.edu% !!
a.out
fill time = 0.58
ni_fill time = 1.89
v_fill time = 4.41
g.oswego.edu%
So inlining gave a > 2.5X speedup over noninlines, and > 5X over
virtuals on the Sparc. It's not too hard to make examples where it's
closer to 10X.
The code generated for inline fill() is about the best you could get
anywhere:
_fill__FR10Vec1000000f:
!#PROLOGUE# 0
save %sp,-112,%sp
!#PROLOGUE# 1
mov %i1,%o2
sethi %hi(1000000),%o0
or %lo(1000000),%o0,%o0
mov %i0,%o1
sll %o0,2,%o0
b L672
add %o0,%i0,%o0
L677:
st %o2,[%o1]
add %o1,4,%o1
L672:
cmp %o1,%o0
bl L677
nop
ret
restore
-Doug
Re: lack of inline functions in libg++
Author: Dirk Grunwald
Date: Thu, 26 Oct 1989 16:08
Date: Thu, 26 Oct 1989 16:08
18 lines
1426 bytes
1426 bytes
I think that a lot of the effort spent on ``cleaning up inlining'' & the like would be better spent on global optimization, although that process is much harder. I'm thinking of things along the lines of the compilation to symbolic intermediate (rtl?), and later ``linking'' of the intermediate form followed by a global procedure integration & register allocation pass. Examples of this include the MIPS compilers (using ucode as intermediate) and the work at DEC-WRL for the titan (mahler intermediate code). This allows much better procedure integration and you'll improve register allocation in leaf procedures. Also, it would make G++ much nicer because your header files would only include class declerations - there would be not need to include inline procedure bodies in the header files.
lack of inline functions in libg++
Author: Michael Tiemann
Date: Thu, 26 Oct 1989 16:17
Date: Thu, 26 Oct 1989 16:17
53 lines
1483 bytes
1483 bytes
The code generated for inline fill() is about the best you could get
anywhere:
_fill__FR10Vec1000000f:
!#PROLOGUE# 0
save %sp,-112,%sp
!#PROLOGUE# 1
mov %i1,%o2
sethi %hi(1000000),%o0
or %lo(1000000),%o0,%o0
mov %i0,%o1
sll %o0,2,%o0
b L672
add %o0,%i0,%o0
L677:
st %o2,[%o1]
add %o1,4,%o1
L672:
cmp %o1,%o0
bl L677
nop
ret
restore
-Doug
No, that code is bad. GCC with my scheduling extensions would make
code which looked like this (honest!):
_fill__FR10Vec1000000f:
!#PROLOGUE# 0
!#PROLOGUE# 1
sethi %hi(1000000),%o2
or %lo(1000000),%o2,%o2
sll %o2,2,%o2
add %o2,%o0,%o2
st %o1,[%o0]
L677:
add %o0,4,%o0
L672:
cmp %o0,%o2
bl L678
st %o1,[%o0]
ret
nop
or something like it. There's lots of fun you can have with an
optimizer.
Michael
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads