Memory outputs in inline asm
Richard Sandiford
rsandifo@linux.vnet.ibm.com
Wed Feb 26 14:33:00 GMT 2014
Michael Matz <matz@suse.de> writes:
> On Wed, 26 Feb 2014, Richard Biener wrote:
>> > "\tstr wzr, [%2, #4]!\n"
>> > "\tsub %1, %1, #1\n"
>> > "\tcbnz %1, 0b\n"
>> > : "=m"(*p), "+r"(len) : "r"(p));
>> >
>> > I presume this is wrong because *p only refers to p[0]. Is it
>> > possible to tell GCC that the asm writes to the whole block of memory
>> > reachable from p without a total memory clobber?
>> >
>> > I have attached some code that works but it is so fugly that I'm
>> > reluctant to recommend it.
>>
>> Well, you are surely lucky at the moment because nothing in GCC
>> disambiguates asms with memory operands against anything.
>>
>> But yes, technically you write p[0] here but as "m" merely builds
>> an address to the memory I'd say that we have to treat any "m"
>> operand as possibly reading from / writing to / clobbering the
>> whole object that can be refered to using that address.
>>
>> Anything else would need extra syntax to specify a memory
>> range that is accessed.
>
> And we have that (as you found out downthread), and it's even documented
> for inline asms, I'll cite:
>
> ---------------------------------------
> If your assembler instructions access memory in an unpredictable
> fashion, add `memory' to the list of clobbered registers.
> ...
> If you know how large the accessed memory is, you can add it as input or
> output but if this is not known, you should add `memory'. As an example,
> if you access ten bytes of a string, you can use a memory input like:
>
> {"m"( ({ struct { char x[10]; } *p = (void *)ptr ; *p; }) )}.
> ---------------------------------------
>
> So, I don't think there's any need to redefine '"m"(*p)' to mean anything
> else than p[0].
>
>> And yes, I probably should implement at least basic disambiguation
>> against memory accessing asm()s ;)
>>
>> Summary: I consider your asm ok without changes.
>
> I don't.
Same here FWIW.
I assume DSE was using MEM_SIZE to determine how big the memory
reference is. MEM_SIZE should always be accurate, and if an rtl
pattern is:
(insn ... (set (mem X [S4]) Y))
then the only memory clobbered should be the 4 bytes at X.
So if we do decide to go with the "whole object might be clobbered"
interpretation, I think the right fix is to force MEM_SIZE to be 0
in that case, rather than change DSE specifically.
Thanks,
Richard
More information about the Gcc
mailing list