non-optimal code with volatile vars

Ralf Gütlein ralf.guetlein@aranea.de
Fri Dec 31 20:54:00 GMT 1999


----------
> Von: Mike Stump <mrs@windriver.com>
> I just looked at the uses of volatile_ok, and I must say, it is a bad
> idea (or maybe just a bad implementation).  Not sure why it is even in
> there, maybe someone else can elaborate?  In any event, it seems like
> a hack.
> Now, why is it a bad idea?  Because there are only two uses of it, and
> in those two uses, there are three bugs.  The bugs are obvious (watch
> the control flow and the restoration of volatile_ok).  If we supported
> frame based cleanup actions in C, and used them, there wouldn't be any
> bugs.
> I think a .md that doesn't want volatile mem refs in an instruction,
> can go out of its way to reject or reload the value, instead of
> penalizing all insns in all .mds as it does now.

That's the point! I still can't imagine why a volatile mem ref
should *not* be a general_operand in some compiler passes.

Does anybody remember when this ominous volatile_ok has found it's way
into gcc? Apparently, the code around this flag is incomplete and
provisional (see comments in sources). Maybe its inserted only to
hack around an error in a single target implementation, or sth.
I cannot see why this hack should penalize all other targets in
which it is safe to use volatiles as a general_operand.

In big OS-based applications this penalty isn't that serious, becaus
there won't be many volatiles. But it's a MUST for embedded
applications to optimally handle volatile mem refs, as these are
used for i/o ports and other peripherals. Consider a code sequence
to implement a synchronous serial output (H8300 specific, but
generally applicable). 


GCC-2.95.1 compiles:                  Patched version compiles:

 void ser_out(unsigned char data)     void ser_out(unsigned char data)     
 {                                    {                                    
   int i;                               int i;                             
   for (i=7; i!=0; i--)                 for (i=7; i!=0; i--)               
         mov.w   #7,r3                        mov.w   #7,r2                
 .L6:                                 .L6:                                 
   {                                    {                                  
    Port |= CLOCK;                       Port |= CLOCK;                    
         mov.b   @_Port:8,r                   bset    #0,@_Port:8          
         or      #1,r2l                  if (data&1)                       
         mov.b   r2l,@_Port                   btst    #0,r0l               
    if (data&1)                               beq     .L7                  
         btst    #0,r0l                    Port |= DATA;                   
         beq     .L7                          bset    #1,@_Port:8          
      Port |= DATA;                           bra     .L8                  
         mov.b   @_Port:8,r           .L7:                                 
         or      #2,r2l                  else                              
         bra     .L11                      Port &= ~DATA;                  
 .L7:                                         bclr    #1,@_Port:8          
    else                              .L8:                                 
      Port &= ~DATA;                     Port &= ~CLOCK;                   
         mov.b   @_Port:8,r                   bclr    #0,@_Port:8          
         and     #253,r2l                data >>= 1;                       
 .L11:                                        shlr    r0l                  
         mov.b   r2l,@_Port             }                                  
    Port &= ~CLOCK;                           subs #1,r2                   
         mov.b   @_Port:8,r                   mov.w   r2,r2                
         and     #254,r2l                     bne     .L6                  
         mov.b   r2l,@_Port           }                                    
    data >>= 1;                               rts                          
         shlr    r0l       
   }                       
         subs #1,r3        
         mov.w   r3,r3     
         bne     .L6       
 }
         rts               


In the right column you see the result of the patch I applied
to h8300.c (see first message of this thread).
The relevant code for shifting a bit out of the serial port
(contents of the for() loop) is 8 instructions in contrast
to 15 instructions for the unpatched compiler.

The moral of this story:
The code around volatile_ok should be revised urgently!


Regards,
Ralf

------------
mind the new e-mail address!
it is now  <ralf.guetlein at aranea dot de>



More information about the Gcc-bugs mailing list