C++ suffers on another inner loop
Iain McClatchie
iainmcc@ix.netcom.com
Fri Apr 24 16:23:00 GMT 1998
Ah. I'm a blockhead. Excuse me, Nathan, for being too square to
realize you were joking.
I did a little more poking around and reduced the test case
considerably. As it turns out, the problem has nothing to do with
C++, templates, or anything like that. It's just when the compiler
inlines a function, it turns off some low-level optimizations that
it would have done had the function been inlined by hand.
The actual problem that one sees depends on the boolean expression
inlined. Here's a much simpler example:
typedef struct hte_t {
struct hte_t *next;
const char *str;
} hte_t;
hte_t * lookup1__FP5hte_tPCc:
lookup1( hte_t *list, const char *str ) pushl %ebp
{ movl %esp,%ebp
for( ; list; list = list->next ) { movl 8(%ebp),%eax
if( list->str == str ) movl 12(%ebp),%edx
return list; testl %eax,%eax
} je .L8
return list; .align 4
} .L5:
cmpl %edx,4(%eax)
je .L8
movl (%eax),%eax
testl %eax,%eax
jne .L5
.L8:
movl %ebp,%esp
popl %ebp
ret
inline int
match( const char *str1, const char *str2 )
{
return ( str1 == str2 );
}
hte_t * lookup2__FP5hte_tPCc:
lookup2( hte_t *list, const char *str ) pushl %ebp
{ movl %esp,%ebp
for( ; list; list = list->next ) { movl 8(%ebp),%eax
if( match( str, list->str )) movl 12(%ebp),%edx
return list; .align 4
} .L11:
return list; testl %eax,%eax
} je .L17
cmpl %edx,4(%eax)
je .L17
In lookup2, egcs should combine the movl (%eax),%eax
end-of-loop test with the branch backward. jmp .L11
It succeeds in lookup1 but fails here, .align 4
presumably because the match function .L17:
is inlined. I think Jason Merrill checked movl %ebp,%esp
in a fix for this sort of thing in popl %ebp
February. ret
It seems that any simple inlined conditional will show the same
symptom. If the inlined conditional is a compound conditional, things
get worse: the code builds up a boolean value only to branch on it:
hte_t * lookup1__FP5hte_tPCc:
lookup1( hte_t *list, const char *str ) pushl %ebp
{ movl %esp,%ebp
for( ; list; list = list->next ) { movl 8(%ebp),%edx
if(( list->str == str ) || movl 12(%ebp),%ec
( list->next == (hte_t *) str )) testl %edx,%edx
return list; je .L3
} .align 4
return list; .L5:
} cmpl %ecx,4(%edx)
je .L3
movl (%edx),%eax
cmpl %ecx,%eax
je .L3
movl %eax,%edx
testl %edx,%edx
jne .L5
.L3:
movl %edx,%eax
movl %ebp,%esp
popl %ebp
ret
inline int lookup2__FP5hte_tPCc:
match( hte_t *list, const char *str ) pushl %ebp
{ movl %esp,%ebp
return(( list->str == str ) || movl 8(%ebp),%eax
( list->next == (hte_t *) str )); movl 12(%ebp),%ec
} .align 4
.L14:
hte_t * testl %eax,%eax
lookup2( hte_t *list, const char *str ) je .L22
{ xorl %edx,%edx
for( ; list; list = list->next ) { cmpl %ecx,4(%eax)
if( match( list, str )) je .L19
return list; cmpl %ecx,(%eax)
} jne .L20
return list; .L19:
} movl $1,%edx
.L20:
testl %edx,%edx
jne .L22
movl (%eax),%eax
jmp .L14
.align 4
.L22:
movl %ebp,%esp
popl %ebp
ret
-Iain McClatchie
More information about the Gcc
mailing list