[llvm-dev] [RFC] Refinement of convergent semantics

Owen Anderson via llvm-dev
2015-09-14T19:30:39Z

> On Sep 14, 2015, at 12:15 PM, Philip Reames <listmail at
philipreames.com> wrote:
>
> On 09/04/2015 01:25 PM, Owen Anderson via llvm-dev wrote:
>> Hi all,
>>
>> In light of recent discussions regarding updating passes to respect
convergent semantics, and whether or not it is sufficient for barriers, I would
like to propose a change in convergent semantics that should resolve a lot of
the identified problems regarding loop unrolling, loop unswitching, etc.  Credit
to John McCall for talking this over with me and seeding the core ideas.
>>
>> Today, convergent operations may only be moved into control-equivalent
locations, or, in layman’s terms, a convergent operation may neither be sunk
into nor hoisted out of, a condition.  This causes problems for full loop
unrolling, as the control dependence on the loop counter is eliminated, but our
intuition indicates that this dependence was somehow trivial.  More concretely,
all know uses of convergent are OK with full unrolling, making this semantic
undesirable.  Related problems arise in loop unswitching as well.
> I don't understand this point.  Loop unrolling specifically won't
change which indices actually run.  It might result in code duplication with a
subset of indices taken one of two paths.  Does today's convergent also
imply no-duplicate?  Is that what you're trying to relax?

The definition today says that we cannot remove a control dependence.  Since the
loop counter is eliminated entirely, one can argue that we have eliminated the
control dependence on it.  I agree that there’s an intuitive argument that the
dependence on the loop counter was trivial, but I have no idea how to formalize
that.

While resolving the question re: loop unrolling is nice, I actually thinking
providing answers on which loop unswitching transforms are legal is actually the
more novel part of this change.

>>
>> The proposed change is to split the semantics of convergent into two
annotations:
>> 	convergent - this operation may not be made control dependent on any
additional values (aka may not be sunk into a condition)
> To be clear, this is a restriction of current semantics only right?

That depends on what you mean by restriction.  It allow strictly more code
motion than is allowed by the current semantics.

>> 	nospeculate - this operation may not be added to any program trace on
which it was not previously executed (same as notrap?)
> Isn't this already true of all instructions?  Unless we can *prove*
that speculating an instruction can't introduce faults, we can't
speculate it ever.  An unknown call or intrinsic should already have this
property right?

Possibly?  We probably need a safetospeculate attribute, then.

>
> This part of the proposal doesn't feel mature to me.  In particular, I
think we need to talk about what other cases we want to handle w.r.t.
speculation attributes and what our model is.
>
> One case I want to support is for small functions which only read argument
memory (i.e. argmemonly readonly nounwind) which are guaranteed (by the
frontend) to fault only if a) the pointer passed in is null, or b) the memory
state on entry is different that the one the context should have ensured.  (The
second part is standard. The first allows speculation in more cases.)
>
> I'd suggest promoting this to it's own thread.  Once we settle on a
workable model for safe speculation attributes, we can revisit how we want to
change the convergent attribute.

We can certainly start a separate conversation about safe speculation attribute.
If what you suggest is true that we already treat intrinsics conservatively WRT
speculation, then I don’t think we need to block progress on convergent on that.

—Owen