On 08/20/2017 06:59 PM, Alan Modra wrote: > On Sun, Aug 20, 2017 at 08:00:53AM -0500, Segher Boessenkool wrote: >> Hi Alan, >> >> On Sat, Aug 19, 2017 at 12:19:35AM +0930, Alan Modra wrote: >>> +Flushing registers to memory has performance implications and may be >>> +an issue for time-sensitive code. You can provide better information >>> +to GCC to avoid this, as shown in the following examples. At a >>> +minimum, aliasing rules allow GCC to know what memory @emph{doesn't} >>> +need to be flushed. Also, if GCC can prove that all of the outputs of >>> +a non-volatile @code{asm} statement are unused, then the @code{asm} >>> +may be deleted. Removal of otherwise dead @code{asm} statements will >>> +not happen if they clobber @code{"memory"}. >> >> void f(int x) { int z; asm("hcf %0,%1" : "=r"(z) : "r"(x) : "memory"); } >> void g(int x) { int z; asm("hcf %0,%1" : "=r"(z) : "r"(x)); } >> >> Both f and g are completely removed by the first jump pass immediately >> after expand (via delete_trivially_dead_insns). >> >> Do you have a testcase for the behaviour you saw? > > Oh my. I was sure that was how "memory" worked! I see though that > every gcc I have lying around, going all the way back to gcc-2.95, > deletes the asm in your testcase. I definitely don't want to put > something in the docs that is plain wrong, or just my idea of how > things ought to work, so the last two sentences quoted above need to > go. Thanks for the correction. > > Fixed in this revised patch. The only controversial aspect now should > be whether those array casts ought to be officially blessed. I've > checked that "=m" (*(T (*)[]) ptr), "=m" (*(T (*)[n]) ptr), and > "=m" (*(T (*)[10]) ptr), all generate reasonable MEM_ATTRS handled > apparently properly by alias.c and other code. > > For example, at -O3 the following shows gcc moving the read of "val" > before the asm, while an asm using a "memory" clobber forces the read > to occur after the asm. > > static int > f (double *x) > { > int res; > asm ("#%0 %1 %2" : "=r" (res) : "r" (x), "m" (*(double (*)[]) x)); > return res; > } > > int val = 123; > double foo[10]; > > int > main () > { > int b = f (foo); > __builtin_printf ("%d %d\n", val, b); > return 0; > } > > > I'm also encouraged by comments like the following by rth in 2004 > (gcc/c/c-typeck.c), which say that using non-kosher lvalues in memory > output constraints must continue to be supported. > > /* ??? Really, this should not be here. Users should be using a > proper lvalue, dammit. But there's a long history of using casts > in the output operands. In cases like longlong.h, this becomes a > primitive form of typechecking -- if the cast can be removed, then > the output operand had a type of the proper width; otherwise we'll > get an error. Gross, but ... */ > STRIP_NOPS (output); > > > * doc/extend.texi (Clobbers): Correct vax example. Delete old > example of a memory input for a string of known length. Move > commentary out of table. Add a number of new examples > covering array memory inputs. > testsuite/ > * gcc.target/i386/asm-mem.c: New test. OK. Sorry about the long wait.
jeff