GCC Bugzilla has been upgraded from version 4.4.9 to 5.0rc3. If you see any problem, please report it to bug 64968.
Bug 56476 - ARM volatile writes/str creates superfluous and uncalled for read/ldr with -Os
Summary: ARM volatile writes/str creates superfluous and uncalled for read/ldr with -Os
Status: RESOLVED DUPLICATE of bug 56098
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.7.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2013-02-27 19:23 UTC by Jesse Off
Modified: 2013-02-27 19:46 UTC (History)
1 user (show)

See Also:
Host:
Target: arm-linux-gnueabi
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jesse Off 2013-02-27 19:23:11 UTC
Gcc 4.7.1 crosscompiler ARM EABI target, x86 Linux host.

In the below code, there are only writes to the "regs" volatile unsigned int *.

Yet, compiling with "-Os", "-O2", or "-O -ftree-vrp" yields code that will do an uncalled for ldrne in the assembler output.  This is bad as this volatile unsigned int * represents hardware registers where bus reads have side-effects and reading a value and then writing the same value back to the same location is not an equivalent operation to doing nothing at all.

Several gcc versions have been tested and all but some really old 3.3.4 gcc toolchain exhibited this. (4.6.1 and a 4.4.4 were tested also and had the bug)

//Jesse Off



volatile unsigned int * regs;                                         
                                                                      
void test(void)                                                       
{                                                                     
    int i, x;                                                         
                                                                      
    regs[0x708 / 4] = 0xdeadbeef;                                     
                                                                      
    for (i = 0xbad; i >= 0; i--) {                                    
        if (i == 1)                                                   
            regs[0x708 / 4] = 0xbeefdead;                             
        for (x = 1; x >= 0; x--) {                                    
            regs[0x708 / 4] = 0xbadcab;                               
            regs[0x704 / 4] = x;                                      
        }                                                             
    }                                                                 
}                                                                     
                                                                      
/*                                                                    
                                                                      
BROKEN ASM!!!! (Compiled with -Os)                                         
                                                                      
00000000 <test>:                                                      
   0:   e59f3048        ldr     r3, [pc, #72]   ; 50 <test+0x50>      
   4:   e59f2048        ldr     r2, [pc, #72]   ; 54 <test+0x54>      
   8:   e5933000        ldr     r3, [r3]                              
   c:   e92d4010        push    {r4, lr}                              
  10:   e59f1040        ldr     r1, [pc, #64]   ; 58 <test+0x58>      
  14:   e5832708        str     r2, [r3, #1800] ; 0x708               
  18:   e59f203c        ldr     r2, [pc, #60]   ; 5c <test+0x5c>      
  1c:   e3a04001        mov     r4, #1                                
  20:   e3a0c000        mov     ip, #0                                
  24:   e3520001        cmp     r2, #1                                
  28:   15930708        ldrne   r0, [r3, #1800] ; 0x708               
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- NOT SAFE!  
                                                                      
  2c:   059f002c        ldreq   r0, [pc, #44]   ; 60 <test+0x60>      
  30:   e2522001        subs    r2, r2, #1                            
  34:   e5830708        str     r0, [r3, #1800] ; 0x708               
  38:   e5831708        str     r1, [r3, #1800] ; 0x708               
  3c:   e5834704        str     r4, [r3, #1796] ; 0x704               
  40:   e5831708        str     r1, [r3, #1800] ; 0x708               
  44:   e583c704        str     ip, [r3, #1796] ; 0x704               
  48:   2afffff5        bcs     24 <test+0x24>                        
  4c:   e8bd8010        pop     {r4, pc}                              
  50:   00000000        .word   0x00000000                            
  54:   deadbeef        .word   0xdeadbeef                            
  58:   00badcab        .word   0x00badcab                            
  5c:   00000bad        .word   0x00000bad                            
  60:   beefdead        .word   0xbeefdead                            
                                                                      
                                                                      
RIGHT AND WORKING (Compiled with -O) (no superfluous ldr on a volatile)                              
                                                                      
00000000 <test>:                                                      
   0:   e52d4004        push    {r4}            ; (str r4, [sp, #-4]!)
   4:   e59f304c        ldr     r3, [pc, #76]   ; 58 <test+0x58>      
   8:   e5933000        ldr     r3, [r3]                              
   c:   e59f2048        ldr     r2, [pc, #72]   ; 5c <test+0x5c>      
  10:   e5832708        str     r2, [r3, #1800] ; 0x708               
  14:   e59f2044        ldr     r2, [pc, #68]   ; 60 <test+0x60>      
  18:   e59f1044        ldr     r1, [pc, #68]   ; 64 <test+0x64>      
  1c:   e3a0c001        mov     ip, #1                                
  20:   e3a00000        mov     r0, #0                                
  24:   e59f403c        ldr     r4, [pc, #60]   ; 68 <test+0x68>      
  28:   ea000001        b       34 <test+0x34>                        
  2c:   e3520001        cmp     r2, #1                                
  30:   05834708        streq   r4, [r3, #1800] ; 0x708               
  34:   e5831708        str     r1, [r3, #1800] ; 0x708               
  38:   e583c704        str     ip, [r3, #1796] ; 0x704               
  3c:   e5831708        str     r1, [r3, #1800] ; 0x708               
  40:   e5830704        str     r0, [r3, #1796] ; 0x704               
  44:   e2422001        sub     r2, r2, #1                            
  48:   e3720001        cmn     r2, #1                                
  4c:   1afffff6        bne     2c <test+0x2c>                        
  50:   e8bd0010        pop     {r4}                                  
  54:   e12fff1e        bx      lr                                    
  58:   00000000        .word   0x00000000                            
  5c:   deadbeef        .word   0xdeadbeef                            
  60:   00000bad        .word   0x00000bad                            
  64:   00badcab        .word   0x00badcab                            
  68:   beefdead        .word   0xbeefdead                            
                                                                      
*/
Comment 1 Andrew Pinski 2013-02-27 19:41:43 UTC
The tree pass CSElim is doing this for some reason.  I think it forgot to check for volatileness.
Comment 2 Andrew Pinski 2013-02-27 19:46:16 UTC
Already fixed for 4.7.3 and above.

*** This bug has been marked as a duplicate of bug 56098 ***