bcopy/memmove optimization broken ? [looks like you are correct to me, I give supporting detail]
Mark Millard
markmi at dsl-only.net
Sat Feb 11 02:11:33 UTC 2017
On 2017-Feb-10, at 7:51 AM, Alexandre Martins <alexandre.martins at stormshield.eu> wrote:
> Hi all
>
> I see in the kernel code of bcopy/memmove an optimization if the copied region
> don't overlap:
>
> https://svnweb.freebsd.org/base/head/sys/arm/arm/support.S?view=annotate#l403
>
> I'm a newbie in ARM assembly, so, sorry if i'm wrong, but
> - R0 is the dst (1st parameter)
> - R1 is the src (2nd parameter)
>
> So :
> subcc r3, r0, r1 /* if (dst > src) r3 = dst - src */
> subcs r3, r1, r0 /* if (src > dsr) r3 = src - dst */
> cmp r3, r2 /* if (r3 < len) we have an overlap */
> bcc PIC_SYM(_C_LABEL(memcpy), PLT)
>
> Seems to be inverted. Should it be that ? :
> subcs r3, r0, r1 /* if (dst > src) r3 = dst - src */
> subcc r3, r1, r0 /* if (src > dsr) r3 = src - dst */
> cmp r3, r2 /* if (r3 < len) we have an overlap */
> bcs PIC_SYM(_C_LABEL(memcpy), PLT)
>
>
> Best regards
>
> --
> Alexandre Martins
> STORMSHIELD
I did not expect something so central that has been
around so long to look wrong but. . .
Going through the supporting details of the original
code based on my looking around here is what I found:
#include <string.h>
void *memmove(void *dest, const void *src, size_t n);
So I'd expect (c'ish notation):
r0==dest
r1==src
r2==n
Then for (the comments vs. code is being challenged):
(The comments do seem to give the intent correctly.)
cmp r0, r1
RETeq /* Bail now if src/dst are the same */
subcc r3, r0, r1 /* if (dst > src) r3 = dst - src */
subcs r3, r1, r0 /* if (src > dsr) r3 = src - dst */
cmp r3, r2 /* if (r3 < len) we have an overlap */
bcc PIC_SYM(_C_LABEL(memcpy), PLT)
. . .
cmp r0,r1 should result in condition code (c'ish notation):
eq=(r0==r1)
cc=(r0<r1)
cs=(r0>=r1)
(Only the r0 position has no immediate-value alternative.)
subcc r3,r0,r1 is: if (cc) r3=r0-r1 // no condition code change
In other words: if (dst<src) r3=dst-src
So it does not match the test listed in the comment as
far as I can see. And in (mathematical) integer arithmetic
the r3 result would be negative for dst-src. For
non-negative arithmetic (natural or whole): undefined.
subcs r3,r1,r0 is: if (cs) r3=r1-r0 // no condition code change
In other words: if (dst>=src) r3=src-dst
So it does not match the test listed in the comment as
far as I can see. And in (mathematical) integer arithmetic
the r3 result would be nonpositive for src-dst. But the
earlier RETeq prevents the zero case, so: negative. For
non-negative arithmetic (natural or whole): undefined.
If it was only a normal mathemetical context r3=-abs(dst-src)
would be a summary of the two sub instruction sequence as it
is from what I can tell.
For the purpose the summary should be: r3=abs(dst-src), given
dst!=src . There is no need to wonder outside normal
mathematical non-negative arithmetic in the process either.
Your code change would have the right summary and use only
normal mathematical rules from what I can tell:
cmp r0, r1
RETeq /* Bail now if src/dst are the same */
subcs r3, r0, r1 /* if (dst > src) r3 = dst - src */
subcc r3, r1, r0 /* if (src > dsr) r3 = src - dst */
cmp r3, r2 /* if (r3 < len) we have an overlap */
bcs PIC_SYM(_C_LABEL(memcpy), PLT)
. . .
subcs r3,r0,r1 is: if (cs) r3=r0-r1 // no condition code change
In other words: if (dst>=src) r3=dst-src.
Given the prior RETeq, that is effectively: if (dst>src) r3=dst-src.
And that matches the comments and would produce a positive result
for r3, matching the normal mathematical result.
subcc r3,r1,r0 is: if (cc) r3=r1-r0 // no condition code change
In other words: if (dst<src) r3=src-dst
And that matches the comments and would produce a positive result
for r3, matching the normal mathematical result.
Overall summary of the two updated sub?? instructions:
r3=abs(dst-src), given dst!=src.
And that would make for an appropriate comparison to n (i.e., to r2).
It appears to have been as it is now since -r143175 when memmove was
added to sys/arm/arm/support.S (2005-Apr-12).
===
Mark Millard
markmi at dsl-only.net
More information about the freebsd-arm
mailing list