
Hi,
It seems to me that both GCC 6.3 and 6.4 mis-compiles arch/arm/mach-imx/syscounter.c.
I'm attaching two files, bad.txt is the original syscounter.c and good.txt is the one with the following patch.
diff --git a/arch/arm/mach-imx/syscounter.c b/arch/arm/mach-imx/syscounter.c index 9290918dca..30ed0109a2 100644 --- a/arch/arm/mach-imx/syscounter.c +++ b/arch/arm/mach-imx/syscounter.c @@ -82,7 +82,7 @@ unsigned long long get_ticks(void) { unsigned long long now;
- asm("mrrc p15, 0, %Q0, %R0, c14" : "=r" (now)); + asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (now));
gd->arch.tbl = (unsigned long)(now & 0xffffffff); gd->arch.tbu = (unsigned long)(now >> 32);
The target code is the while loop in the __udelay. void __udelay(unsigned long usec) { unsigned long long tmp; ulong tmo;
tmo = us_to_tick(usec); tmp = get_ticks() + tmo; /* get current timestamp */
while (get_ticks() < tmp) /* loop till event */ /*NOP*/; }
Here is the mis compiled asm from the above code (whole function is attached as bad.txt)
88: 428b cmp r3, r1 8a: f8ce 20a4 str.w r2, [lr, #164] ; 0xa4 8e: bf08 it eq 90: 4282 cmpeq r2, r0 92: f8ce 30a0 str.w r3, [lr, #160] ; 0xa0 96: d3f7 bcc.n 88 <__udelay+0x88>
Note that the last bcc.n to 88 and we don't see mrrc.
This seems to be that both get_ticks() are inlined and "mrrc"s are duplicated in the __udealy() and GCC sees it as an opportunity to optimize out.
GCC 5 and 8 seems to work fine. Unfortunately I don't have GCC 7 ATM so no idea how it compiles.
Does anyone see this?