Bug 20972 - Register allocator/reload uses auto-inc register in non-addressing operand
Summary: Register allocator/reload uses auto-inc register in non-addressing operand
Status: RESOLVED WORKSFORME
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 4.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ra, wrong-code
Depends on:
Blocks:
 
Reported: 2005-04-12 16:51 UTC by Joshua Conner
Modified: 2010-07-20 14:06 UTC (History)
6 users (show)

See Also:
Host:
Target: arm-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-01-15 21:17:11


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Joshua Conner 2005-04-12 16:51:22 UTC
Test gcc.c-torture/compile/930210-1.c, when compiled with:

    -O2 -c

produces the warning:

    /var/tmp//ccSVOi5X.s: Assembler messages:
    /var/tmp//ccSVOi5X.s:23: Warning: source register same as write-back base

Because of the following instruction generated in the assembly:

    strb    r2, [r2], #1

The assembler warning is produced because the instruction is unpredictable when the source register 
and the base destination register are the same and post-increment addressing is used.

Note that while this test doesn't fail for the arm-none-elf target, a similar test case does demonstrate 
the same issue:

void f(void)
{
  char  c1, c2;
  char *p1, *p2;

  c1 = c2 = *p1++;
  while (c1--)
    *p2++ = *p1++;
}

This behavior is present in gcc-4.1.0-20050405, and gcc-4.0.0-20050410 (RC1).
Configuration options: --target=arm-unknown-elf --program-prefix=arm-elf- --disable-nls --
enable-languages=c,c++ --with-newlib --enable-multilib --disable-shared
Comment 1 Andrew Pinski 2005-04-12 17:08:16 UTC
Patch here: <http://gcc.gnu.org/ml/gcc-patches/2005-04/msg01291.html>.

Do you know if this is a regression from say 3.4.x?
Comment 2 Joshua Conner 2005-04-12 17:24:24 UTC
Subject: Re:  Compiler-generated code produces an assembler warning

I don't see this same behavior on 3.4.3.

- Josh

On Apr 12, 2005, at 10:08 AM, pinskia at gcc dot gnu dot org wrote:

>
> ------- Additional Comments From pinskia at gcc dot gnu dot org   
> 2005-04-12 17:08 -------
> Patch here: <http://gcc.gnu.org/ml/gcc-patches/2005-04/msg01291.html>.
>
> Do you know if this is a regression from say 3.4.x?
>
> --  
>            What    |Removed                     |Added
> ----------------------------------------------------------------------- 
> -----
>                  CC|                            |pinskia at gcc dot  
> gnu dot
>                    |                            |org
>              Status|UNCONFIRMED                 |NEW
>      Ever Confirmed|                            |1
>            Keywords|                            |patch
>    Last reconfirmed|0000-00-00 00:00:00         |2005-04-12 17:08:16
>                date|                            |
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20972
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
>

Comment 3 Richard Earnshaw 2005-05-12 11:36:05 UTC
The ARM ARM says that

  STR Rd, [Rn], #4

and 

  STR Rd, [Rn, #4]!

are unpredictable if Rd == Rn.  That is, the auto-inc side effect is permitted
to take place before Rd is read.
 
There's currently no way for a back-end to describe that an auto-inc operation
might be an early-clobber.  The obvious '&<>' in the constraint doesn't work,
causing an abort in find_reloads().

This bug isn't really a regression (the limitation has always been there), but
the vagaries of register allocation means that it is only recently that it's
started doing this (either that, or the assembler has only recently started
whining about it :-).
Comment 4 Mark Mitchell 2005-07-06 16:53:41 UTC
Postponed until 4.0.2.
Comment 5 Paolo Bonzini 2005-10-13 16:01:27 UTC
Maybe you could add a reload_completed split to not use autoincrements if Rd == Rn?
Comment 6 Andrew Pinski 2005-10-16 21:42:52 UTC
As described by Richard, this is not a regression so therefor not marking as such.
Comment 7 Jorn Wolfgang Rennecke 2006-02-14 21:27:46 UTC
(In reply to comment #3)
> There's currently no way for a back-end to describe that an auto-inc operation
> might be an early-clobber.  The obvious '&<>' in the constraint doesn't work,
> causing an abort in find_reloads().
Actually, according to rtl.texi, there is no way to describe an auto-inc operation that is not an early-clobber at all.
They are basically an earlyclobber for insns that do/would fit for a load-store architecture.  If you have more than one memory address in the insn, it gets
more complicated, as rtl.texi makes a distiction between address and non-address
uses:

If a register used as the operand of these expressions is used in
another address in an insn, the original value of the register is used.
Uses of the register outside of an address are not permitted within the
same insn as a use in an embedded side effect expression because such
insns behave differently on different machines and hence must be treated
as ambiguous and disallowed.
Comment 8 Richard Earnshaw 2006-02-15 10:03:17 UTC
OK, then that moves this from being a minor into a more serious problem.  The compiler is clearly failing to behave as specified.
Comment 9 David Edelsohn 2006-06-17 01:37:53 UTC
The bug is in flow.c and fixed by the new df.c rewrite of dataflow.  Ken and I tripped over the same problem.
Comment 10 Kenneth Zadeck 2006-06-17 04:14:22 UTC
(In reply to comment #9)
> The bug is in flow.c and fixed by the new df.c rewrite of dataflow.  Ken and I
> tripped over the same problem.
> 

While I thought this earlier, I do not believe it now.  There is a problem in flow  that it fails to generate reg-dead notes for dead index regs in auto-inc insns, but this is a separate problem.  
Comment 11 Jan Hubicka 2008-09-06 12:02:05 UTC
Also just noticed that offline copy of longest-match get extra move:
.L15:   
        movzbl  2(%eax), %edi   #, tmp87
        leal    2(%eax), %ecx   #, scan.158
        movl    %edi, %edx      # tmp87,
        cmpb    2(%ebx), %dl    #,
        jne     .L6     #,
        movzbl  3(%eax), %edi   #, tmp88
        leal    3(%eax), %ecx   #, scan.158
        movl    %edi, %edx      # tmp88,
        cmpb    3(%ebx), %dl    #,
        jne     .L6     #,      
        movzbl  4(%eax), %edi   #, tmp89
        leal    4(%eax), %ecx   #, scan.158
        movl    %edi, %edx      # tmp89,
        cmpb    4(%ebx), %dl    #,
        jne     .L6     #,
        movzbl  5(%eax), %edi   #, tmp90
        leal    5(%eax), %ecx   #, scan.158
        movl    %edi, %edx      # tmp90,
        cmpb    5(%ebx), %dl    #,
        jne     .L6     #,
 
while inlined copy is fine:
.L98:   
        movzbl  1(%eax), %edx   #,
        leal    1(%eax), %edi   #, scan
        cmpb    1(%ecx), %dl    #,
        jne     .L161   #,
        movzbl  2(%eax), %edx   #,
        leal    2(%eax), %edi   #, scan
        cmpb    2(%ecx), %dl    #,
        jne     .L161   #,
        movzbl  3(%eax), %edx   #,
        leal    3(%eax), %edi   #, scan
        cmpb    3(%ecx), %dl    #,
        jne     .L161   #,
        movzbl  4(%eax), %edx   #,
        leal    4(%eax), %edi   #, scan
        cmpb    4(%ecx), %dl    #,
        jne     .L161   #,
interesting :)
Comment 12 Steven Bosscher 2009-09-26 09:58:20 UTC
Is there still a bug here, after the IRA merge?
Comment 13 Ramana Radhakrishnan 2009-12-22 22:39:32 UTC
Can't reproduce with trunk or release branches for the attached testcase. 
Comment 14 Steven Bosscher 2010-07-20 14:06:12 UTC
If it works for Ramana, it works for me.