Bug 45094

Summary: [arm] wrong instructions for dword move in some cases
Product: gcc Reporter: Akos PASZTORY <akos.pasztory>
Component: targetAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: armin76, gcc-bugs, qiyao, rhill, siarhei.siamashka, toolchain
Priority: P3 Keywords: wrong-code
Version: 4.5.0   
Target Milestone: 4.6.0   
Host: i486-linux-gnu Target: arm-linux-gnueabi
Build: i486-linux-gnu Known to work:
Known to fail: Last reconfirmed: 2010-07-27 12:47:57
Attachments: simplified testcase

Description Akos PASZTORY 2010-07-27 11:34:19 UTC
gcc 4.5.0

$ cat /tmp/bug.c
extern int printf(const char *fmt, ...);
void foo(void *x) { printf("%p\n", x); }
void bar(long long *x) { printf("%lld ", *x); foo(x); }

int main()
{
	bar(&(long long){0ll});
	bar(&(long long){1ll});
	bar(&(long long){2ll});
	bar(&(long long){3ll});
	bar(&(long long){4ll});
	bar(&(long long){5ll});
	bar(&(long long){6ll});
	bar(&(long long){7ll});
	bar(&(long long){8ll});
	bar(&(long long){9ll});
	bar(&(long long){10ll});
	bar(&(long long){11ll});
	bar(&(long long){12ll});
	bar(&(long long){13ll});
	bar(&(long long){14ll});
	bar(&(long long){15ll});
	bar(&(long long){16ll});
	bar(&(long long){17ll});
	bar(&(long long){18ll});
	bar(&(long long){19ll});
	bar(&(long long){20ll});
	bar(&(long long){21ll});
	bar(&(long long){22ll});
	bar(&(long long){23ll});
	bar(&(long long){24ll});
	bar(&(long long){25ll});
	bar(&(long long){26ll});
	bar(&(long long){27ll});
	bar(&(long long){28ll});
	bar(&(long long){29ll});
	bar(&(long long){30ll});
	bar(&(long long){31ll});
	bar(&(long long){32ll});
	bar(&(long long){33ll});
	bar(&(long long){34ll});
	bar(&(long long){35ll});
	bar(&(long long){36ll});
	bar(&(long long){37ll});
	bar(&(long long){38ll});
	bar(&(long long){39ll});
	bar(&(long long){40ll});
	bar(&(long long){41ll});
	bar(&(long long){42ll});
	bar(&(long long){43ll});
	bar(&(long long){44ll});
	return 0;
}

$ cc -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -S -O2 /tmp/bug.c

inspect bug.s.  for a while gcc emits correct instructions:

...
        mov     r2, #29
        mov     r3, #0
        strd    r2, [r0, #-240]!
        bl      bar
        add     r0, sp, #360
        mov     r2, #30
        mov     r3, #0
        strd    r2, [r0, #-248]!
        bl      bar

however when reaching offset -256, it emits LDRs instead of STRs:

        add     r0, sp, #360
        mov     r2, #31
        mov     r3, #0
        ldr     r2, [r0, #-256]!
        ldr     r3, [r0, #4]
        bl      bar

the issue seems to be a typo in gcc/config/arm/arm.c:output_move_double() introduced by commit [1].  i've tried to fix by applying the following:

--- ../gcc-4.5.0/gcc/config/arm/arm.c.orig	2010-07-27 14:22:42.000000000 +0300
+++ ../gcc-4.5.0/gcc/config/arm/arm.c	2010-07-27 14:23:05.000000000 +0300
@@ -12182,13 +12182,13 @@ output_move_double (rtx *operands)
 	    {
 	      if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
 		{
-		  output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
-		  output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
+		  output_asm_insn ("str%?\t%0, [%1, %2]!", otherops);
+		  output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
 		}
 	      else
 		{
-		  output_asm_insn ("ldr%?\t%H0, [%1, #4]", otherops);
-		  output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
+		  output_asm_insn ("str%?\t%H0, [%1, #4]", otherops);
+		  output_asm_insn ("str%?\t%0, [%1], %2", otherops);
 		}
 	    }
 	  else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)

[1] http://repo.or.cz/w/official-gcc.git/commitdiff/f1225f6f0f9b7acb3a64314f2113807ebeea5abf?hp=78f46d4510475cdb9532b10787e82b476c9eeef1
Comment 1 Ramana Radhakrishnan 2010-07-27 12:47:57 UTC
Patches should be submitted to gcc-patches@gcc.gnu.org after having been regression tested. Please also submit a testcase and appropriate Changelog entries as documented here -  http://gcc.gnu.org/contribute.html#patches


Having said that however, this patch looks alright to me from the naked eye and code inspection.

Comment 2 Siarhei Siamashka 2010-07-27 20:07:07 UTC
Created attachment 21327 [details]
simplified testcase

Confirmed with gcc 4.5.0 here. Also tried but could not reproduce the problem with gcc 4.4 (it just does not seem to be able to emit ldrd/strd instructions with pre/post increment).
Comment 3 Yao Qi 2010-08-01 08:44:10 UTC
(In reply to comment #2)
> Created an attachment (id=21327) [edit]
> simplified testcase

Update this test case a little bit, with test commands.
Post patch here http://gcc.gnu.org/ml/gcc-patches/2010-08/msg00001.html
 

Comment 4 Akos PASZTORY 2010-08-01 11:18:40 UTC
> Post patch here http://gcc.gnu.org/ml/gcc-patches/2010-08/msg00001.html

+		  output_asm_insn ("strr%?\t%H0, [%1, #4]", otherops);

s/strr/str/ ?
Comment 5 Yao Qi 2010-08-02 00:38:59 UTC
(In reply to comment #4)
> > Post patch here http://gcc.gnu.org/ml/gcc-patches/2010-08/msg00001.html
> 
> +                 output_asm_insn ("strr%?\t%H0, [%1, #4]", otherops);
> 
> s/strr/str/ ?
> 
Right, it is a typo.  Latest patch is posted here,
http://gcc.gnu.org/ml/gcc-patches/2010-08/msg00018.html
Comment 6 Yao Qi 2010-08-18 12:34:07 UTC
Subject: Bug 45094

Author: qiyao
Date: Wed Aug 18 12:33:43 2010
New Revision: 163338

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=163338
Log:
gcc/
        PR target/45094
        * config/arm/arm.c (output_move_double): Fix typo generating 
        instructions ('ldr'->'str').

gcc/testsuite/

        PR target/45094
        * gcc.target/arm/pr45094.c: New test.

Added:
    trunk/gcc/testsuite/gcc.target/arm/pr45094.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/arm/arm.c
    trunk/gcc/testsuite/ChangeLog

Comment 7 Ramana Radhakrishnan 2010-08-27 12:14:09 UTC
can this be backported to the 4.5 branch please ? 
Comment 8 Richard Biener 2010-12-16 13:03:16 UTC
GCC 4.5.2 is being released, adjusting target milestone.
Comment 9 Siarhei Siamashka 2010-12-18 15:43:39 UTC
Can this bug get a "[4.5 regression]" header please?

Even though the bug existed in gcc sources since 2007 (see the link in comment 1), the reported wrong-code problem itself was apparently latent until gcc 4.5, and is not reproducible with older gcc versions.
Comment 10 Siarhei Siamashka 2010-12-18 15:47:12 UTC
(In reply to comment #9)
> see the link in comment 1

Sorry, I mean the link in the original report from Akos:
http://repo.or.cz/w/official-gcc.git/commitdiff/f1225f6f
Comment 11 Yao Qi 2010-12-27 08:35:21 UTC
Patch to backport it to 4.5 is here http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01858.html
Comment 12 Ryan Hill 2010-12-28 00:47:14 UTC
Is that first hunk intentional?
Comment 13 Yao Qi 2010-12-28 01:48:51 UTC
(In reply to comment #12)
> Is that first hunk intentional?
 
No.  It is from another PR backport, so it is redundant here.  Submit a clean patch again http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01873.html
Comment 14 Andrew Pinski 2012-01-12 20:34:14 UTC
Fixed in 4.6.0.