Optimization breaks inline asm code w/ptrs
Andrew Pinski
pinskia@gmail.com
Sun Aug 13 05:40:00 GMT 2017
On Sat, Aug 12, 2017 at 10:08 PM, Andrew Pinski <pinskia@gmail.com> wrote:
> 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.
I should ask why are you using inline-asm for this? strlen will have
the best optimized version for your processor anyways.
Thanks,
Andrew
> 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