[cfe-dev] Speculative load optimization

Kevin Choi via cfe-dev cfe-dev at lists.llvm.org
Mon Oct 9 20:21:48 PDT 2017


I suspect

>         r = ((T*)s)->p1;

Is allowed under C99 ยง6.5, strict aliasing rule
An object shall have its stored value accessed only by an lvalue expression
that has one of the following types
...
- an aggregate or union type that includes one of the aforementioned types
among its members (including, recursively, a member of a subaggregate or
contained union)

CMIIW, the cmov optimizer may be pessimistic here -- access to one path
implies object is non-null, dereferenceable by compatible types.

-Kevin


On Mon, Oct 9, 2017 at 8:00 PM, Hans Wennborg via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> I am not a language lawyer, but I'll atttempt to answer anyway.
>
> On Mon, Oct 9, 2017 at 2:16 PM, Kreitzer, David L via cfe-dev
> <cfe-dev at lists.llvm.org> wrote:
> > This llvm patch, https://reviews.llvm.org/D37289, attempts to do an
> optimization
> > that involves speculating loads. The patch itself needs some work
> regardless,
> > but we are questioning the legality of the optimization, which is
> currently
> > performed by both gcc and icc. The desired transformation looks like
> this:
> >
> >     typedef struct S {
> >       char padding[4088];
> >       struct S *p1;
> >       struct S *p2;
> >     } S;
> >
> >     struct S* f1(struct S *s, int x)
> >     {
> >       S *r;
> >       if (x)
> >         r = s->p1;
> >       else
> >         r = s->p2;
> >       return r;
> >     }
> >
> > TO
> >
> >     struct S* f1(struct S *s, int x)
> >     {
> >       return (x) ? s->p1 : s->p2;
> >     }
> >
> > The fundamental question seems to be whether loading one member of
> struct S
> > makes it valid to load other members of the same struct.
>
> Yes, I believe that's true. If we're dereferencing s on both paths, it
> must point to a struct S object, and then loading from any member of
> that object should be fine.
>
> > Both gcc & icc
> > seem to think so and make a distinction between this case and a similar
> case
> > where one field is accessed through an lvalue of a different type:
> >
> >     typedef struct T {
> >       char padding[4088];
> >       struct S *p1;
> >     } T;
> >
> >     struct S* f2(struct S *s, int x)
> >     {
> >       S *r;
> >       if (x)
> >         r = ((T*)s)->p1;
> >       else
> >         r = s->p2;
> >       return r;
> >     }
> >
> > Neither compiler will transform this case.
>
> I suspect it would be within the compiler's rights, but my language
> knowledge is too weak. Does the cast imply that s points to a valid
> struct S object (or null, but then we couldn't dereference it)? I'm
> curious to find out :-)
>
>  - Hans
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20171009/ae122aad/attachment.html>


More information about the cfe-dev mailing list