[PATCH] D23214: [MDA] Treat invariant.start as non-dependence
Sanjoy Das via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 8 14:57:44 PDT 2016
Hi Daniel,
Daniel Berlin wrote:
> FWIW: I've pretty much not thought about it at all.
> The main use case, as far as i remember, was to support specifying
> invariantness that otherwise could not be inferred through analysis.
> I believe the only use case in my part of the world (C++) is const
> objects of various sorts, or write-once objects.
>
> Neither would be broken by this kind of merging.
>
> If we do think the above kind of merging is okay, we should mark
> invariant.end readonly as well and teach a small set of things not to
> hoist them/eat them, so that we gain the benefits of them not blocking
> optimization either (for example, any readnone/readonly function that
> uses invariants is still going to be marked readwrite due to the
> invariant.end)
I meant to mention this in my previous mail, but we'd need some
special handling / logic to not DCE them away if we mark them as
readonly.
-- Sanjoy
>
>
> This can even be a valuable optimization in cases where the
> "<non-memory affecting instruction>" bits were hidden behind a call
> that was later inlined.
>
> The way I see it is that invariant_start and invariant_end denote the
> boundaries of a region that can be assumed to not have stores to a
> specific location[1]. To preserve this property we only need to
avoid
> stores floating into the region, and for that readonly semantics is
> sufficient for non-atomic accesses (and potentially some kinds of
> atomic accesses too). Readonly semantics may even be stronger
than we
> need, since I think we can allow stores floating *out* of the region.
>
>
> Yes, that sounds right.
>
>
> I'm not yet fully confident that the above semantics will hold under
> pressure, since it fails the test of "can I write an
implementation of
> invariant_start and invariant_end that will give me the guarantees I
> need?". The best I can do with invariant_start and invariant_end as
> specified is:
>
> void* invariant_start(iN* ptr) {
> cell = malloc(sizeof(iN));
> *(iN*)cell = ptr;
> return cell;
> }
>
> void invariant_end(void* cell, iN* ptr) {
> assert(*(iN*)cell == *ptr);
> }
>
>
> which still allows the transform:
>
> x = invariant_start(ptr)
> int val = *ptr;
> print(val);
> invariant_end(x, ptr)
>
> ==>
>
> x = invariant_start(ptr)
> int val_backup = *ptr;
> *ptr = 400;
> *ptr = val_backup;
> int val = *ptr;
> print(val);
> invariant_end(x, ptr)
>
>
> That's not a clear problem (after all, intrinsics are allowed to have
> special semantics that may not be "implementable" in IR), but it is a
> "slightly red" flag.
>
>
>
> yeah. I guess it would be interesting to know what real world uses for
> this currently exist.
>
>
> [1]: An alternate framing would be: no stores to that specific
> location change the contained value.
>
> -- Sanjoy
>
>
> >
> > GVN is not quite smart enough yet, but it's about to be.
> >
> > GCC even has testcases that we both eliminate and PRE pure/const
> > (readonly/readnone) calls.
>
>
More information about the llvm-commits
mailing list