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