Re: [RFD] Using the 'memory constraint' trick to avoid memory clobber doesn't work
I've forgot if someone mentioned whether we have a test-case in our test-suite for this feature. I'm looking thru gcc/testsuite/*.c to see if I can spot anything. It's not easy since there is a lot of asm and the people who write these are apparently allergic to using comments to describe what they are testing. So, I found a few tests that were *using* this feature. But they seem to be checking for an ICE or page fault, rather than checking to see if the generated code was avoiding the memory clobber. dw
Re: Request for discussion: Rewrite of inline assembler docs
On 3/31/2014 1:41 AM, Andrew Haley wrote: On 03/31/2014 05:44 AM, dw wrote: So, after looking over this discussion, I have updated the text. This time no undefined terms, while still conveying all the points I had in mind: The "memory" clobber tells the compiler that the assembly code performs memory reads or writes to items other than those listed in the input and output operands (for example accessing the memory pointed to by one of the input parameters). To ensure memory contains correct values, GCC may need to flush specific register values to memory before executing the asm. Further, the compiler will not assume that any values read from memory before the @code{asm} will remain unchanged after the @code{asm}; it will reload them as needed. This effectively forms a read/write memory barrier for the compiler. Note that this clobber does not prevent the @emph{processor} from doing speculative reads past the @code{asm} statement. To stop that, you need processor-specific fence instructions. Objections? No, none. That's fine. Done. I believe all the proposed changes are now included. The latest extend.texi and extend.texi.patch can be found in (http://www.LimeGreenSocks.com/gcc/extend05.zip) and the latest html pages are at (http://www.LimeGreenSocks.com/gcc/Using-Assembly-Language-with-C.html). If you were expecting a change and it isn't there, let me know. Anyone else have something before I send this to gcc-patches? Going... going...
Re: Request for discussion: Rewrite of inline assembler docs
So, after looking over this discussion, I have updated the text. This time no undefined terms, while still conveying all the points I had in mind: The "memory" clobber tells the compiler that the assembly code performs memory reads or writes to items other than those listed in the input and output operands (for example accessing the memory pointed to by one of the input parameters). To ensure memory contains correct values, GCC may need to flush specific register values to memory before executing the asm. Further, the compiler will not assume that any values read from memory before the @code{asm} will remain unchanged after the @code{asm}; it will reload them as needed. This effectively forms a read/write memory barrier for the compiler. Note that this clobber does not prevent the @emph{processor} from doing speculative reads past the @code{asm} statement. To stop that, you need processor-specific fence instructions. Objections? dw
Re: Request for discussion: Rewrite of inline assembler docs
Looks great to me. Just noticed one small nit: in the extended asm section, "=irm" isn't valid, since you can't assign to an immediate. Doh! I probably copied this from the Input section. Good catch. Also, in the section about clobbers: It causes the compiler to flush all registers to memory before executing the asm statement. At first I read this as meaning "all registers are saved somewhere in memory before the asm". Maybe something like "flush all pending stores"? Not sure whether that's better or not though. You are right, and this is an important point. I have re-worked this whole paragraph. Old: It causes the compiler to flush all registers to memory before executing the |asm| statement. Further, the compiler will not assume that any values read before the |asm| will remain unchanged after the |asm|; it will reload them as needed. This effectively forms a read/write barrier for the compiler. New: Using this clobber causes the compiler to flush all (modified) registers being used to store memory-based values to memory before executing the @code{asm} statement. Further, the compiler will not assume that any memory-based values read before the @code{asm} will remain unchanged after the @code{asm}; it will reload them as needed. This effectively forms a read/write memory barrier for the compiler. For performance reasons, some variables only exist in registers and never get written to memory. The "memory" clobber does not force these values to get written to memory. Thanks again for all the work on this. Anything else? Richard
Re: Request for discussion: Rewrite of inline assembler docs
I think it really is general though. In: The same problem can occur if one output parameter (@var{a}) allows a register constraint, is updating the parameter value, and references an address while another output parameter (@var{b}) allows a memory constraint. Yep, you're right. I have trimmed this back to just: The same problem can occur if one output parameter (@var{a}) allows a register constraint and another output parameter (@var{b}) allows a memory constraint. Seems like that's the last of it then. I've updated the web pages (http://www.LimeGreenSocks.com/gcc/Using-Assembly-Language-with-C.html) if you want to look at how it turned out. Unless you have something else, I'm going to start composing the email for gcc-patches. Thanks for the help. dw
Re: Request for discussion: Rewrite of inline assembler docs
On 3/25/2014 4:20 AM, Richard Sandiford wrote: dw writes: asm ("" : "=m" (*x), "=r" (y)); you have to assume that the address in %0 might use the same register as %1 Ok, now I'm getting there. It helps that I've compiled some examples and can see what is happening. This one is subtle. I'm going to have to go back and review my code to see if I've ever done this. So, the existing text (which only talks about overlaps with input parameters) reads: "Unless an output operand has the '&' constraint modifier (see Modifiers), GCC may allocate it in the same register as an unrelated input operand, on the assumption that the assembler code will consume its inputs before producing outputs. This assumption may be false if the assembler code actually consists of more than one instruction. In this case, use '&' for each output operand that must not overlap an input." I'm thinking about adding something like this after it: "The same problem can occur if one of the output parameters allows a register constraint and contains an address. In this case, GCC may use maybe "...and another output parameter contains..."? Filtering that through: the same register for this parameter as it does for other output parameters that allow a memory constraint. This can produce inconsistent results if the register address is updated before updating the memory address. Combining the '&' constraint with the register constraint prevents this overlap and resolves the inconsistency." That's as clear as I can come up with. Better? how about: The same problem can occur if one output parameter @var{a} allows a register constraint and another output parameter @var{b} allows a memory constraint. The memory address in @var{b} may contain registers and GCC treats those registers as inputs to the asm. As above, GCC assumes that such input registers are consumed before any outputs are written. If in fact the asm writes to @var{a} before @var{b}, it may inadvertently change the address used for @var{b}. Combining the '&' constraint with the register constraint prevents this overlap and ensures that @var{a} and @var{b} can be written in either order. Not sure that's much good though, sorry. That helps alot. Of course I had to fiddle with it just a bit more... While adding the '&' ensures that modifying @var{a} will not affect what address is referenced by @var{b}, I worry that someone might assume by implication that *omitting* it means that b will always follow a. But I don't believe that's guaranteed. It seems like it might, or it might not depending on the "whims" of the optimizer, with tiny changes in "unrelated" code swinging things back and forth. Also, I believe the problem is slightly more limited than the language above (both yours and mine) implies. These points plus some minor languages changes gives me: The same problem can occur if one output parameter (@var{a}) allows a register constraint, is updating the parameter value, and references an address while another output parameter (@var{b}) allows a memory constraint. The code generated by GCC to access the memory address in @var{b} can contain registers which @emph{might} be shared by @var{a}, and GCC considers those registers to be inputs to the asm. As above, GCC assumes that such input registers are consumed before any outputs are written. This assumption may result in incorrect behavior if the asm writes to @var{a} before using @var{b}. Combining the '@code{&}' constraint with the register constraint ensures that modifying @var{a} will not affect what address is referenced by @var{b}. Omitting the '@code{&}' constraint means that the location of @var{b} will be undefined if @var{a} is modified before using @var{b}. Done? Thanks, Richard
Re: Request for discussion: Rewrite of inline assembler docs
Sorry for the slow response. Thanks for getting back to me. I was pretty sure I didn't have this all quite right yet. asm ("" : "=m" (*x), "=r" (y)); you have to assume that the address in %0 might use the same register as %1 Ok, now I'm getting there. It helps that I've compiled some examples and can see what is happening. This one is subtle. I'm going to have to go back and review my code to see if I've ever done this. So, the existing text (which only talks about overlaps with input parameters) reads: "Unless an output operand has the '&' constraint modifier (see Modifiers), GCC may allocate it in the same register as an unrelated input operand, on the assumption that the assembler code will consume its inputs before producing outputs. This assumption may be false if the assembler code actually consists of more than one instruction. In this case, use '&' for each output operand that must not overlap an input." I'm thinking about adding something like this after it: "The same problem can occur if one of the output parameters allows a register constraint and contains an address. In this case, GCC may use the same register for this parameter as it does for other output parameters that allow a memory constraint. This can produce inconsistent results if the register address is updated before updating the memory address. Combining the '&' constraint with the register constraint prevents this overlap and resolves the inconsistency." That's as clear as I can come up with. Better? dw
Re: Request for discussion: Rewrite of inline assembler docs
On 3/21/2014 2:57 AM, James Greenhalgh wrote: On Thu, Feb 27, 2014 at 11:07:21AM +, Andrew Haley wrote: Over the years there has been a great deal of traffic on these lists caused by misunderstandings of GCC's inline assembler. That's partly because it's inherently tricky, but the existing documentation needs to be improved. dw has done a fairly thorough reworking of the documentation. I've helped a bit. Section 6.41 of the GCC manual has been rewritten. It has become: 6.41 How to Use Inline Assembly Language in C Code 6.41.1 Basic Asm - Assembler Instructions with No Operands 6.41.2 Extended Asm - Assembler Instructions with C Expression Operands We could simply post the patch to GCC-patches and have at it, but I think it's better to discuss the document here first. You can read it at This documentation looks like a huge improvement. Thanks, I've worked hard to make it so. As the discussion here seems to have stalled, perhaps it is time to propose the patch to gcc-patches? Sorry, I wanted to make sure the people who were discussing it had a chance to finish responding, then I got caught up in other projects. I'll try to roll the comments into the docs this weekend. I'm certainly keen to see this make it to trunk, the increase in clarity is substantial. Exactly so. Trying to figure this all out from the existing docs drove me crazy. That's what motivated me to fix this. My goal is to make it so the next guy who has to struggle with this has an easier time than I did. Thanks, James
Re: Request for discussion: Rewrite of inline assembler docs
On 3/3/2014 3:36 AM, Richard Sandiford wrote: dw writes: On 2/27/2014 11:32 PM, Richard Sandiford wrote: dw writes: On 2/27/2014 4:11 AM, Richard Sandiford wrote: Andrew Haley writes: Over the years there has been a great deal of traffic on these lists caused by misunderstandings of GCC's inline assembler. That's partly because it's inherently tricky, but the existing documentation needs to be improved. dw has done a fairly thorough reworking of the documentation. I've helped a bit. Section 6.41 of the GCC manual has been rewritten. It has become: 6.41 How to Use Inline Assembly Language in C Code 6.41.1 Basic Asm - Assembler Instructions with No Operands 6.41.2 Extended Asm - Assembler Instructions with C Expression Operands We could simply post the patch to GCC-patches and have at it, but I think it's better to discuss the document here first. You can read it at http://www.LimeGreenSocks.com/gcc/Basic-Asm.html http://www.LimeGreenSocks.com/gcc/Extended-Asm.html http://www.LimeGreenSocks.com/gcc/extend04.zip (contains .texi, .patch, and affected html pages) All comments are very welcome. Thanks for doing this, looks like a big improvement. Thanks, I did my best. I appreciate you taking the time to review them. A couple of comments: The section on basic asms says: Do not expect a sequence of asm statements to remain perfectly consecutive after compilation. To ensure that assembler instructions maintain their order, use a single asm statement containing multiple instructions. Note that GCC's optimizer can move asm statements relative to other code, including across jumps. The "maintain their order" might be a bit misleading, since volatile asms (including basic asms) must always be executed in the original order. Maybe this was meaning placement/address order instead? This statement is based on this text from the existing docs: "Similarly, you can't expect a sequence of volatile |asm| instructions to remain perfectly consecutive. If you want consecutive output, use a single |asm|." I do not dispute what you are saying. I just want to confirm that the existing docs are incorrect before making a change. Also, see Andi's response re -fno-toplevel-reorder. It seems to me that recommending "single statement" is both the clearest, and the safest approach here. But I'm prepared to change my mind if there is consensus I should. Right. I agree with that part. I just thought that the "maintain their order" could be misunderstood as meaning execution order, whereas I think both sentences of the original docs were talking about being "perfectly consecutive" (which to me means "there are no other instructions inbetween"). Hmm. I'm not seeing the differences here that you do. Well, like you say, things can be moved across branches. So, although this is a very artificial example: asm ("x"); asm ("y"); could become: goto bar; foo: asm ("y"); ... bar: asm ("x"); goto foo; This has reordered the instructions in the sense that they have a different order in memory. But they are still _executed_ in the same order. Actually reordering the execution would be a serious bug. So I just want to avoid anything that gives the impression that "y" can be executed before "x" in this example. I still think: Since the existing docs say "GCC's optimizer can move asm statements relative to other code", how would you feel about: "Do not expect a sequence of |asm| statements to remain perfectly consecutive after compilation. If you want to stop the compiler from reordering or inserting anything into a sequence of assembler instructions, use a single |asm| statement containing multiple instructions. Note that GCC's optimizer can move |asm| statements relative to other code, including across jumps." ...this gives the impression that we might try to execute volatiles in a different order. Ahh! Ok, I see what you mean. Hmm. Based on the description of "no-toplevel-reorder", I assumed that it actually *might* re-order them. So, more like: "GCC's optimizer can move asm statements relative to other code, including across jumps. This has implications for code that contains a sequence of asm statements. While the execution order of asm statements will be preserved, do not expect the sequence of asm statements to remain perfectly consecutive in the compiler's output. To ensure that assembler instructions maintain their order, use a single asm statement containing multiple instructions." It might also be worth mentioning that the number of instances of an asm in the output may be different from the input. (Can it increase as well as decrease? I'm not sure off-hand, but probably y
Re: Request for discussion: Rewrite of inline assembler docs
On 2/27/2014 8:12 PM, Andi Kleen wrote: dw writes: What would you say to something like this: "Since GCC does not parse the asm, it has no visibility of any static variables or functions it references. This may result in those symbols getting discarded by GCC as unused. To avoid this problem, list the symbols as inputs or outputs." output makes no sense I think, only input. For static functions, yes. However won't static data have the same problem? And static data could be input or output. You still need the part about the top-level asm, where input doesn't work. Accessing variables from Basic asm has more problems than this. If you are inside a function that accesses globals from both asm and C, the results will probably be a mess. That's why the current docs for Basic asm say: "Safely accessing C data and calling functions from Basic |asm| is more complex than it may appear. To access C data, it is better to use Extended |asm|. " However, you are right, more is needed. How about: "For asm blocks outside of functions (which must be Basic asm), be aware that since GCC does not parse the asm, it has no visibility of any static variables or functions it references. This may result in those symbols getting discarded by GCC as unused." And another common problem: For top level asm there is no guarantee the compiler outputs the statements in order. Well, basic asm (which is the only thing you can use at top level) already says: "Do not expect a sequence of |asm| statements to remain perfectly consecutive after compilation. To ensure that assembler instructions maintain their order, use a single |asm| statement containing multiple instructions. Note that GCC's optimizer can move |asm| statements relative to other code, including across jumps. " Is something more needed? Yes it should be made clear that this applies to top-level asm too. I believe what you call "top level" the docs call "Basic asm." This same statement is in both sections. -Andi
Re: Request for discussion: Rewrite of inline assembler docs
On 2/27/2014 9:35 AM, Andi Kleen wrote: Andrew Haley writes: Over the years there has been a great deal of traffic on these lists caused by misunderstandings of GCC's inline assembler. That's partly because it's inherently tricky, but the existing documentation needs to be improved. dw has done a fairly thorough reworking of the documentation. I've helped a bit. It would be nice if you could include some discussion of the LTO reference problems. Something like: It is not legal to reference a static variable or function symbol from the assembler code, as the compiler may optimize unused symbols away. For inline asm in functions these should be referred as "m" input arguments. For top level asm the referenced symbol should be made global and marked with __attribute__((externally_visible)) . What would you say to something like this: "Since GCC does not parse the asm, it has no visibility of any static variables or functions it references. This may result in those symbols getting discarded by GCC as unused. To avoid this problem, list the symbols as inputs or outputs." And another common problem: For top level asm there is no guarantee the compiler outputs the statements in order. Well, basic asm (which is the only thing you can use at top level) already says: "Do not expect a sequence of |asm| statements to remain perfectly consecutive after compilation. To ensure that assembler instructions maintain their order, use a single |asm| statement containing multiple instructions. Note that GCC's optimizer can move |asm| statements relative to other code, including across jumps. " Is something more needed? [unless -fno-toplevel-reorder is specified, but I'm not should mention that] -Andi
Re: Request for discussion: Rewrite of inline assembler docs
On 2/27/2014 4:22 AM, Kyrill Tkachov wrote: On 27/02/14 11:07, Andrew Haley wrote: Over the years there has been a great deal of traffic on these lists caused by misunderstandings of GCC's inline assembler. That's partly because it's inherently tricky, but the existing documentation needs to be improved. dw has done a fairly thorough reworking of the documentation. I've helped a bit. Section 6.41 of the GCC manual has been rewritten. It has become: 6.41 How to Use Inline Assembly Language in C Code 6.41.1 Basic Asm - Assembler Instructions with No Operands 6.41.2 Extended Asm - Assembler Instructions with C Expression Operands We could simply post the patch to GCC-patches and have at it, but I think it's better to discuss the document here first. You can read it at http://www.LimeGreenSocks.com/gcc/Basic-Asm.html http://www.LimeGreenSocks.com/gcc/Extended-Asm.html http://www.LimeGreenSocks.com/gcc/extend04.zip (contains .texi, .patch, and affected html pages) All comments are very welcome. Hi Andrew, dw, Thanks for doing this! Thanks for taking the time to review it. In the Extended Asm documentation: Other format strings section: "'%=' outputs a number that is unique to each instruction in the entire compilation." I find the term 'instruction' to be confusing here. From what I understand the number is unique to each asm statement, which may contain multiple assembly instructions. IMHO it would be clearer to say "unique to each asm statement" I'm not sure your text quite gets us there either. If (as Richard suggests), the asm can get duplicated, I'd expect each to get a unique value for %=. And I'd want to be clear about what happens if you do #define DO_SOMETHING asm("%=":). How would you feel about: "'%=' outputs a number that is unique to each instance of the asm statement in the entire compilation." Kyrill Andrew.
Re: Request for discussion: Rewrite of inline assembler docs
On 2/27/2014 4:11 AM, Richard Sandiford wrote: Andrew Haley writes: Over the years there has been a great deal of traffic on these lists caused by misunderstandings of GCC's inline assembler. That's partly because it's inherently tricky, but the existing documentation needs to be improved. dw has done a fairly thorough reworking of the documentation. I've helped a bit. Section 6.41 of the GCC manual has been rewritten. It has become: 6.41 How to Use Inline Assembly Language in C Code 6.41.1 Basic Asm - Assembler Instructions with No Operands 6.41.2 Extended Asm - Assembler Instructions with C Expression Operands We could simply post the patch to GCC-patches and have at it, but I think it's better to discuss the document here first. You can read it at http://www.LimeGreenSocks.com/gcc/Basic-Asm.html http://www.LimeGreenSocks.com/gcc/Extended-Asm.html http://www.LimeGreenSocks.com/gcc/extend04.zip (contains .texi, .patch, and affected html pages) All comments are very welcome. Thanks for doing this, looks like a big improvement. Thanks, I did my best. I appreciate you taking the time to review them. A couple of comments: The section on basic asms says: Do not expect a sequence of asm statements to remain perfectly consecutive after compilation. To ensure that assembler instructions maintain their order, use a single asm statement containing multiple instructions. Note that GCC's optimizer can move asm statements relative to other code, including across jumps. The "maintain their order" might be a bit misleading, since volatile asms (including basic asms) must always be executed in the original order. Maybe this was meaning placement/address order instead? This statement is based on this text from the existing docs: "Similarly, you can't expect a sequence of volatile |asm| instructions to remain perfectly consecutive. If you want consecutive output, use a single |asm|." I do not dispute what you are saying. I just want to confirm that the existing docs are incorrect before making a change. Also, see Andi's response re -fno-toplevel-reorder. It seems to me that recommending "single statement" is both the clearest, and the safest approach here. But I'm prepared to change my mind if there is consensus I should. It might also be worth mentioning that the number of instances of an asm in the output may be different from the input. (Can it increase as well as decrease? I'm not sure off-hand, but probably yes.) So, in the volatile section, how about something like this for decrease: "GCC does not delete a volatile |asm| if it is reachable, but may delete it if it can prove that control flow never reaches the location of the instruction." For increase (not quite sure where to put this yet): "Under certain circumstances, GCC may duplicate your asm code as part of optimization. This can lead to unexpected duplicate symbol errors during compilation if symbols or labels are being used. Using %= (see Assembler Template) may help resolve this problem." In the extended section: Unless an output operand has the '&' constraint modifier (see Modifiers), GCC may allocate it in the same register as an unrelated input operand, [...] It could also use it for addresses in other (memory) outputs. Ok. But I'm not sure this really adds anything. Having warned people that the register may be re-used unless '&' is used seems sufficient. For: When using asmSymbolicNames for the output operands, you may use these names instead of digits. it might be worth mentioning that you need the enclosing [...]. Done. Thanks, Richard
Re: [doc] Fixing reference inside Extended-Asm.html
Is the version of texinfo buggy to generate online documentation? Sorry for the delayed response. I was hoping the gcc expert on docs would respond so I could see who that was. I have been doing some work on Extended-Asm.html (see the work in progress at http://www.limegreensocks.com/gcc/Using-Assembly-Language-with-C.html) and I haven't had a problem generating output. dw
Need a copyright assignment and a copyright disclaimer form
I am attempting to submit a patch for the gcc documentation (see http://gcc.gnu.org/ml/gcc-help/2013-04/msg00193.html). I am told that I need to submit one of these two forms. Please send me copies so I can select one and submit it. dw