Optimization breaks inline asm code w/ptrs
Andrew Pinski
pinskia@gmail.com
Sun Aug 13 05:41:00 GMT 2017
On Sat, Aug 12, 2017 at 9:21 PM, David Wohlferd <dw@limegreensocks.com> wrote:
> Environment:
> gcc 6.1
> compiling for 64bit i386
> optimizations: -O2
>
> Consider this simple bit of code (from
> https://stackoverflow.com/a/45656087/2189500):
>
> #include <stdio.h>
>
> int getStringLength(const char *pStr){
>
> int len;
>
> __asm__ (
> "repne scasb\n\t"
> "not %%ecx\n\t"
> "dec %%ecx"
> :"=c" (len), "+D"(pStr)
> :"c"(-1), "a"(0)
> );
>
> return len;
> }
>
> int main()
> {
> char buff[50] = "hello world";
> int a = getStringLength(buff);
> printf("%s: %d\n", buff, a);
> }
>
> This code works as expected and prints out 11. Yay.
>
> However, if you add "buff[4] = 0;" before the call to getStringLength, it
> STILL prints out 11 (when optimizations are enabled), when it should print
> 4.
>
> I would expect this kind of behavior if the asm were in 'main.' But it has
> always been my understanding that function calls performed an implicit
> memory clobber. The fact that this clobber goes away during inlining means
> that code can stop working any time the compiler makes a different decision
> about whether or not to inline a function. Ouch.
>
> And before somebody asks: Adding "+m"(pStr) does not help.
But does adding:
"+m"(*pStr)
Help?
"+m"(pStr) Just says pStr variable changes, not what it points to.
Thanks,
Andrew Pinski
>
> The result is that (apparently) you can NEVER safely pass a buffer pointer
> to inline asm without using the memory clobber. If this is true, I don't
> believe it is widely known.
>
> Given how 'heavy' memory clobbers are, I would hope that only pointers that
> have 'escaped' the function would get flushed before a function call. But
> not flushing *anything* seems very bad.
>
> dw
>
More information about the Gcc
mailing list