Release novops attribute for external use?
Bingfeng Mei
bmei@broadcom.com
Tue Apr 13 11:35:00 GMT 2010
Thanks! I forgot to declare the function as pure. The empty asm
seems to be a clever trick to avoid function being optimized out.
I shall tell our engineers to use this instead of implementing a new
attribute.
Bingfeng
> -----Original Message-----
> From: Richard Guenther [mailto:richard.guenther@gmail.com]
> Sent: 13 April 2010 11:25
> To: Bingfeng Mei
> Cc: Andrew Haley; gcc@gcc.gnu.org
> Subject: Re: Release novops attribute for external use?
>
> On Tue, Apr 13, 2010 at 12:23 PM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
> > On Tue, Apr 13, 2010 at 12:15 PM, Bingfeng Mei
> <bmei@broadcom.com> wrote:
> >>>
> >>> Surely printf writes to global memory (it clobbers the
> stdout FILE*)
> >>>
> >> OK, the point is not about whether printf is pure or not.
> Instead, if
> >> programmer knows the callee function such as printf contains no
> >> memory access that affects operations inside caller
> function, and he
> >> would like to have a way to optimize the code. Our
> engineer gave following
> >> example:
> >>
> >> void myfunc(MyStruct *myStruct)
> >> {
> >> int a,b;
> >> a = myStruct->a;
> >> printf("a=%d\n",a);
> >> b = 2*mystruct->a; // I would like to have the
> compiler acting as if I had written b = 2*a;
> >> ...
> >> }
> >> Providing such attribute may be potentially dangerous. But
> it is just
> >> like "restrict" qualifier and some other attributes,
> putting responsibilty
> >> of correctness on the programmer. "novops" seems to
> achieve that effect,
> >> though its semantics doesn't match exactly what I described.
> >
> > Indeed. IPA pointer analysis will probably figure it out
> > automagically - that *myStruct didn't escape the unit.
> > Being able to annotate incoming pointers this way would
> > maybe be useful.
> >
> >>> As for the original question - novops is internal only because its
> >>> semantics is purely internal and changes with internal aliasing
> >>> changes.
> >>>
> >>> Now, we still lack a compelling example to see what exact
> semantics
> >>> you are requesting? I suppose it might be close to a pure but
> >>> volatile function? Which you could simulate by
> >>>
> >>> dummy = pure_fn ();
> >>> asm ("" : "g" (dummy));
> >>>
> >>> or even
> >>>
> >>> volatile int dummy = pure_fn ();
> >>
> >> These two methods still generate extra code to reload variables
> >
> > The latter works for me (ok, the store to dummy is retained):
> >
> > extern int myprintf(int) __attribute__((pure));
> > int myfunc (int *p)
> > {
> > int a;
> > a = *p;
> > volatile int dummy = myprintf(a);
> > return a + *p;
> > }
> >
> > myfunc:
> > .LFB0:
> > pushq %rbx
> > .LCFI0:
> > subq $16, %rsp
> > .LCFI1:
> > movl (%rdi), %ebx
> > movl %ebx, %edi
> > call myprintf
> > movl %eax, 12(%rsp)
> > leal (%rbx,%rbx), %eax
> > addq $16, %rsp
> > .LCFI2:
> > popq %rbx
> > .LCFI3:
> > ret
> >
> > so we load from %rdi only once.
>
> And
>
> extern int myprintf(int) __attribute__((pure));
> int myfunc (int *p)
> {
> int a;
> a = *p;
> int dummy = myprintf(a);
> asm ("" : : "g" (dummy));
> return a + *p;
> }
>
> produces
>
> myfunc:
> .LFB0:
> pushq %rbx
> .LCFI0:
> movl (%rdi), %ebx
> movl %ebx, %edi
> call myprintf
> leal (%rbx,%rbx), %eax
> popq %rbx
> .LCFI1:
> ret
>
> even better.
>
> Richard.
>
>
More information about the Gcc
mailing list